oci_config_merge.c 10.6 KB
Newer Older
O
overweight 已提交
1 2
/******************************************************************************
 * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
3 4 5 6
 * iSulad licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
O
overweight 已提交
7 8 9
 * 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.
10
 * See the Mulan PSL v2 for more details.
O
overweight 已提交
11 12 13 14 15 16 17 18 19 20 21 22
 * 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"
H
haozi007 已提交
23
#include "isula_libutils/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
{
L
LiFeng 已提交
30
    if (container_spec->working_dir != NULL || working_dir == NULL) {
O
overweight 已提交
31 32 33
        return;
    }

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

37
static int oci_image_merge_env(const oci_image_spec_config *config, container_config *container_spec)
O
overweight 已提交
38
{
39 40 41 42 43 44 45 46 47
    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 已提交
48 49 50
    if (config->env == NULL || config->env_len == 0) {
        return 0;
    }
51 52

    if (config->env_len > LIST_ENV_SIZE_MAX - container_spec->env_len) {
H
haozi007 已提交
53
        ERROR("The length of envionment variables is too long, the limit is %lld", LIST_ENV_SIZE_MAX);
54 55 56
        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 已提交
57
    }
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
    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 已提交
76
            custom_kv = util_string_split(container_spec->env[j], '=');
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
            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 已提交
99 100
}

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

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

109 110 111 112 113 114 115
    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 已提交
116 117 118 119 120
        ERROR("Out of memory");
        return -1;
    }

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

    return 0;
}

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

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

136 137 138 139 140 141 142
    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 已提交
143 144 145 146 147
        ERROR("Out of memory");
        return -1;
    }

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

    return 0;
}

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

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

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

    return 0;
}

W
wujing 已提交
172 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
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;
}

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

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

static int dup_health_check_from_image(const defs_health_check *image_health_check,
220
                                       container_config *container_spec)
O
overweight 已提交
221 222 223 224 225 226 227 228 229
{
    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;
    }

230 231 232 233 234 235 236
    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 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
    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;

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

    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,
263
                                          container_config *container_spec)
O
overweight 已提交
264
{
265
    if (container_spec->health_check->test_len == 0) {
O
overweight 已提交
266 267
        size_t i;

268 269 270 271 272 273
        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 已提交
274 275 276 277
            ERROR("Out of memory");
            return -1;
        }
        for (i = 0; i < image_health_check->test_len; i++) {
278 279
            container_spec->health_check->test[i] = util_strdup_s(image_health_check->test[i]);
            container_spec->health_check->test_len++;
O
overweight 已提交
280 281
        }
    }
282 283
    if (container_spec->health_check->interval == 0) {
        container_spec->health_check->interval = image_health_check->interval;
O
overweight 已提交
284
    }
285 286
    if (container_spec->health_check->timeout == 0) {
        container_spec->health_check->timeout = image_health_check->timeout;
O
overweight 已提交
287
    }
288 289
    if (container_spec->health_check->start_period == 0) {
        container_spec->health_check->start_period = image_health_check->start_period;
O
overweight 已提交
290
    }
291 292
    if (container_spec->health_check->retries == 0) {
        container_spec->health_check->retries = image_health_check->retries;
O
overweight 已提交
293 294 295 296 297 298
    }

    return 0;
}

static int oci_image_merge_health_check(const defs_health_check *image_health_check,
299
                                        container_config *container_spec)
O
overweight 已提交
300 301 302
{
    int ret = 0;

303
    if (image_health_check == NULL || image_health_check->test_len == 0) {
O
overweight 已提交
304 305 306
        return 0;
    }

307 308
    if (container_spec->health_check == NULL) {
        if (dup_health_check_from_image(image_health_check, container_spec) != 0) {
O
overweight 已提交
309 310 311 312
            ret = -1;
            goto out;
        }
    } else {
313
        if (update_health_check_from_image(image_health_check, container_spec) != 0) {
O
overweight 已提交
314 315 316 317 318 319 320 321 322
            ret = -1;
            goto out;
        }
    }

out:
    return ret;
}

323
int oci_image_merge_config(imagetool_image *image_conf, container_config *container_spec)
O
overweight 已提交
324 325 326
{
    int ret = 0;

327
    if (image_conf == NULL || container_spec == NULL) {
O
overweight 已提交
328 329 330 331 332
        ERROR("Invalid input arguments");
        return -1;
    }

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

335
        if (oci_image_merge_env(image_conf->spec->config, container_spec) != 0) {
O
overweight 已提交
336 337 338 339
            ret = -1;
            goto out;
        }

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

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

W
wujing 已提交
347 348 349 350 351
        if (oci_image_merge_labels(image_conf->spec->config, container_spec) != 0) {
            ret = -1;
            goto out;
        }

352
        // ignore volumes now
O
overweight 已提交
353 354
    }

355
    if (oci_image_merge_health_check(image_conf->healthcheck, container_spec) != 0) {
O
overweight 已提交
356 357 358 359 360 361 362 363
        ret = -1;
        goto out;
    }

out:
    return ret;
}