oci_config_merge.c 10.7 KB
Newer Older
O
overweight 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/******************************************************************************
 * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
 * iSulad licensed under the Mulan PSL v1.
 * You can use this software according to the terms and conditions of the Mulan PSL v1.
 * You may obtain a copy of Mulan PSL v1 at:
 *     http://license.coscl.org.cn/MulanPSL
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v1 for more details.
 * Author: lifeng
 * Create: 2018-11-08
 * Description: provide oci config merge functions
 ******************************************************************************/

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include "oci_config_merge.h"
#include <fcntl.h>              /* Obtain O_* constant definitions */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "utils.h"
#include "log.h"
L
LiuHao 已提交
24
#include "libisulad.h"
O
overweight 已提交
25 26 27
#include "specs_mount.h"
#include "specs_extend.h"

28
static void oci_image_merge_working_dir(const char *working_dir, container_config *container_spec)
O
overweight 已提交
29 30 31 32 33
{
    if (working_dir == NULL) {
        return;
    }

34 35
    free(container_spec->working_dir);
    container_spec->working_dir = util_strdup_s(working_dir);
O
overweight 已提交
36 37
}

38
static int oci_image_merge_env(const oci_image_spec_config *config, container_config *container_spec)
O
overweight 已提交
39
{
40 41 42 43 44 45 46 47 48
    int ret = 0;
    size_t new_size = 0;
    size_t old_size = 0;
    size_t i = 0;
    size_t j = 0;
    char **temp = NULL;
    char **im_kv = NULL;
    char **custom_kv = NULL;

O
overweight 已提交
49 50 51
    if (config->env == NULL || config->env_len == 0) {
        return 0;
    }
52 53 54 55 56 57

    if (config->env_len > LIST_ENV_SIZE_MAX - container_spec->env_len) {
        ERROR("The length of envionment variables is too long, the limit is %d", LIST_ENV_SIZE_MAX);
        isulad_set_error_message("The length of envionment variables is too long, the limit is %d", LIST_ENV_SIZE_MAX);
        ret = -1;
        goto out;
O
overweight 已提交
58
    }
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
    new_size = (container_spec->env_len + config->env_len) * sizeof(char *);
    old_size = container_spec->env_len * sizeof(char *);
    ret = mem_realloc((void **)&temp, new_size, container_spec->env, old_size);
    if (ret != 0) {
        ERROR("Failed to realloc memory for envionment variables");
        ret = -1;
        goto out;
    }

    container_spec->env = temp;
    for (i = 0; i < config->env_len; i++) {
        bool found = false;
        im_kv = util_string_split(config->env[i], '=');
        if (im_kv == NULL) {
            continue;
        }

        for (j = 0; j < container_spec->env_len; j++) {
L
LiFeng 已提交
77
            custom_kv = util_string_split(container_spec->env[j], '=');
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
            if (custom_kv == NULL) {
                continue;
            }
            if (strcmp(im_kv[0], custom_kv[0]) == 0) {
                found = true;
            }
            util_free_array(custom_kv);
            custom_kv = NULL;
            if (found) {
                break;
            }
        }

        if (!found) {
            container_spec->env[container_spec->env_len] = util_strdup_s(config->env[i]);
            container_spec->env_len++;
        }
        util_free_array(im_kv);
        im_kv = NULL;
    }
out:
    return ret;
O
overweight 已提交
100 101
}

102
static int do_duplicate_commands(const oci_image_spec_config *config, container_config *container_spec)
O
overweight 已提交
103 104 105
{
    size_t i;

106
    if (container_spec->cmd_len != 0 || config->cmd_len == 0) {
O
overweight 已提交
107 108 109
        return 0;
    }

110 111 112 113 114 115 116
    if (config->cmd_len > SIZE_MAX / sizeof(char *)) {
        ERROR("too many commands!");
        return -1;
    }

    container_spec->cmd = (char **)util_common_calloc_s(sizeof(char *) * config->cmd_len);
    if (container_spec->cmd == NULL) {
O
overweight 已提交
117 118 119 120 121
        ERROR("Out of memory");
        return -1;
    }

    for (i = 0; i < config->cmd_len; i++) {
122 123
        container_spec->cmd[i] = util_strdup_s(config->cmd[i]);
        container_spec->cmd_len++;
O
overweight 已提交
124 125 126 127 128
    }

    return 0;
}

129
static int do_duplicate_entrypoints(const oci_image_spec_config *config, container_config *container_spec)
O
overweight 已提交
130 131 132 133 134 135 136
{
    size_t i;

    if (config->entrypoint_len == 0) {
        return 0;
    }

137 138 139 140 141 142 143
    if (config->entrypoint_len > SIZE_MAX / sizeof(char *)) {
        ERROR("too many entrypoints!");
        return -1;
    }

    container_spec->entrypoint = (char **)util_common_calloc_s(sizeof(char *) * config->entrypoint_len);
    if (container_spec->entrypoint == NULL) {
O
overweight 已提交
144 145 146 147 148
        ERROR("Out of memory");
        return -1;
    }

    for (i = 0; i < config->entrypoint_len; i++) {
149 150
        container_spec->entrypoint[i] = util_strdup_s(config->entrypoint[i]);
        container_spec->entrypoint_len++;
O
overweight 已提交
151 152 153 154 155
    }

    return 0;
}

156
static int oci_image_merge_entrypoint(const oci_image_spec_config *config, container_config *container_spec)
O
overweight 已提交
157
{
158
    if (container_spec->entrypoint_len != 0) {
O
overweight 已提交
159 160 161
        return 0;
    }

162
    if (do_duplicate_commands(config, container_spec) != 0) {
O
overweight 已提交
163 164 165
        return -1;
    }

166
    if (do_duplicate_entrypoints(config, container_spec) != 0) {
O
overweight 已提交
167 168 169 170 171 172
        return -1;
    }

    return 0;
}

W
wujing 已提交
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
static int make_sure_container_config_labels(container_config *container_spec)
{
    if (container_spec->labels != NULL) {
        return 0;
    }

    container_spec->labels = util_common_calloc_s(sizeof(json_map_string_string));
    if (container_spec->labels == NULL) {
        ERROR("Out of memory");
        return -1;
    }

    return 0;
}

static int oci_image_merge_labels(const oci_image_spec_config *config, container_config *container_spec)
{
    size_t i;

    if (config->labels == NULL || config->labels->len == 0) {
        return 0;
    }

    if (make_sure_container_config_labels(container_spec) != 0) {
        return -1;
    }

    for (i = 0; i < config->labels->len; i++) {
        int ret = append_json_map_string_string(container_spec->labels,
                                                config->labels->keys[i], config->labels->values[i]);
        if (ret < 0) {
            return -1;
        }
    }

    return 0;
}

211
static void oci_image_merge_user(const char *user, container_config *container_spec)
O
overweight 已提交
212
{
213
    if (container_spec->user != NULL) {
O
overweight 已提交
214 215 216
        return;
    }

217
    container_spec->user = util_strdup_s(user);
O
overweight 已提交
218 219 220
}

static int dup_health_check_from_image(const defs_health_check *image_health_check,
221
                                       container_config *container_spec)
O
overweight 已提交
222 223 224 225 226 227 228 229 230
{
    int ret = 0;
    size_t i;
    defs_health_check *health_check = (defs_health_check *)util_common_calloc_s(sizeof(defs_health_check));
    if (health_check == NULL) {
        ERROR("Invalid input arguments");
        return -1;
    }

231 232 233 234 235 236 237
    if (image_health_check->test_len > SIZE_MAX / sizeof(char *)) {
        ERROR("invalid health check commands!");
        ret = -1;
        goto out;
    }

    health_check->test = util_common_calloc_s(sizeof(char *) * image_health_check->test_len);
O
overweight 已提交
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
    if (health_check->test == NULL) {
        ERROR("Out of memory");
        ret = -1;
        goto out;
    }

    for (i = 0; i < image_health_check->test_len; i++) {
        health_check->test[i] = util_strdup_s(image_health_check->test[i]);
        health_check->test_len++;
    }
    health_check->interval = image_health_check->interval;
    health_check->timeout = image_health_check->timeout;
    health_check->start_period = image_health_check->start_period;
    health_check->retries = image_health_check->retries;
    health_check->exit_on_unhealthy = image_health_check->exit_on_unhealthy;

254
    container_spec->health_check = health_check;
O
overweight 已提交
255 256 257 258 259 260 261 262 263

    health_check = NULL;

out:
    free_defs_health_check(health_check);
    return ret;
}

static int update_health_check_from_image(const defs_health_check *image_health_check,
264
                                          container_config *container_spec)
O
overweight 已提交
265
{
266
    if (container_spec->health_check->test_len == 0) {
O
overweight 已提交
267 268
        size_t i;

269 270 271 272 273 274
        if (image_health_check->test_len > SIZE_MAX / sizeof(char *)) {
            ERROR("invalid health check commands!");
            return -1;
        }
        container_spec->health_check->test = util_common_calloc_s(sizeof(char *) * image_health_check->test_len);
        if (container_spec->health_check->test == NULL) {
O
overweight 已提交
275 276 277 278
            ERROR("Out of memory");
            return -1;
        }
        for (i = 0; i < image_health_check->test_len; i++) {
279 280
            container_spec->health_check->test[i] = util_strdup_s(image_health_check->test[i]);
            container_spec->health_check->test_len++;
O
overweight 已提交
281 282
        }
    }
283 284
    if (container_spec->health_check->interval == 0) {
        container_spec->health_check->interval = image_health_check->interval;
O
overweight 已提交
285
    }
286 287
    if (container_spec->health_check->timeout == 0) {
        container_spec->health_check->timeout = image_health_check->timeout;
O
overweight 已提交
288
    }
289 290
    if (container_spec->health_check->start_period == 0) {
        container_spec->health_check->start_period = image_health_check->start_period;
O
overweight 已提交
291
    }
292 293
    if (container_spec->health_check->retries == 0) {
        container_spec->health_check->retries = image_health_check->retries;
O
overweight 已提交
294 295 296 297 298 299
    }

    return 0;
}

static int oci_image_merge_health_check(const defs_health_check *image_health_check,
300
                                        container_config *container_spec)
O
overweight 已提交
301 302 303 304 305 306 307 308 309 310 311 312
{
    int ret = 0;

    if (image_health_check == NULL) {
        return 0;
    }

    if (image_health_check->test_len == 0) {
        ERROR("health check commands required");
        return -1;
    }

313 314
    if (container_spec->health_check == NULL) {
        if (dup_health_check_from_image(image_health_check, container_spec) != 0) {
O
overweight 已提交
315 316 317 318
            ret = -1;
            goto out;
        }
    } else {
319
        if (update_health_check_from_image(image_health_check, container_spec) != 0) {
O
overweight 已提交
320 321 322 323 324 325 326 327 328
            ret = -1;
            goto out;
        }
    }

out:
    return ret;
}

329
int oci_image_merge_config(imagetool_image *image_conf, container_config *container_spec)
O
overweight 已提交
330 331 332
{
    int ret = 0;

333
    if (image_conf == NULL || container_spec == NULL) {
O
overweight 已提交
334 335 336 337 338
        ERROR("Invalid input arguments");
        return -1;
    }

    if (image_conf->spec != NULL && image_conf->spec->config != NULL) {
339
        oci_image_merge_working_dir(image_conf->spec->config->working_dir, container_spec);
O
overweight 已提交
340

341
        if (oci_image_merge_env(image_conf->spec->config, container_spec) != 0) {
O
overweight 已提交
342 343 344 345
            ret = -1;
            goto out;
        }

346
        if (oci_image_merge_entrypoint(image_conf->spec->config, container_spec) != 0) {
O
overweight 已提交
347 348 349 350
            ret = -1;
            goto out;
        }

351
        oci_image_merge_user(image_conf->spec->config->user, container_spec);
O
overweight 已提交
352

W
wujing 已提交
353 354 355 356 357
        if (oci_image_merge_labels(image_conf->spec->config, container_spec) != 0) {
            ret = -1;
            goto out;
        }

358
        // ignore volumes now
O
overweight 已提交
359 360
    }

361
    if (oci_image_merge_health_check(image_conf->healthcheck, container_spec) != 0) {
O
overweight 已提交
362 363 364 365 366 367 368 369
        ret = -1;
        goto out;
    }

out:
    return ret;
}