oci_config_merge.c 9.6 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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
    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++) {
            custom_kv = util_string_split(container_spec->env[i], '=');
            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;
}

173
static void oci_image_merge_user(const char *user, container_config *container_spec)
O
overweight 已提交
174
{
175
    if (container_spec->user != NULL) {
O
overweight 已提交
176 177 178
        return;
    }

179
    container_spec->user = util_strdup_s(user);
O
overweight 已提交
180 181 182
}

static int dup_health_check_from_image(const defs_health_check *image_health_check,
183
                                       container_config *container_spec)
O
overweight 已提交
184 185 186 187 188 189 190 191 192
{
    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;
    }

193 194 195 196 197 198 199
    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 已提交
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
    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;

216
    container_spec->health_check = health_check;
O
overweight 已提交
217 218 219 220 221 222 223 224 225

    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,
226
                                          container_config *container_spec)
O
overweight 已提交
227
{
228
    if (container_spec->health_check->test_len == 0) {
O
overweight 已提交
229 230
        size_t i;

231 232 233 234 235 236
        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 已提交
237 238 239 240
            ERROR("Out of memory");
            return -1;
        }
        for (i = 0; i < image_health_check->test_len; i++) {
241 242
            container_spec->health_check->test[i] = util_strdup_s(image_health_check->test[i]);
            container_spec->health_check->test_len++;
O
overweight 已提交
243 244
        }
    }
245 246
    if (container_spec->health_check->interval == 0) {
        container_spec->health_check->interval = image_health_check->interval;
O
overweight 已提交
247
    }
248 249
    if (container_spec->health_check->timeout == 0) {
        container_spec->health_check->timeout = image_health_check->timeout;
O
overweight 已提交
250
    }
251 252
    if (container_spec->health_check->start_period == 0) {
        container_spec->health_check->start_period = image_health_check->start_period;
O
overweight 已提交
253
    }
254 255
    if (container_spec->health_check->retries == 0) {
        container_spec->health_check->retries = image_health_check->retries;
O
overweight 已提交
256 257 258 259 260 261
    }

    return 0;
}

static int oci_image_merge_health_check(const defs_health_check *image_health_check,
262
                                        container_config *container_spec)
O
overweight 已提交
263 264 265 266 267 268 269 270 271 272 273 274
{
    int ret = 0;

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

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

275 276
    if (container_spec->health_check == NULL) {
        if (dup_health_check_from_image(image_health_check, container_spec) != 0) {
O
overweight 已提交
277 278 279 280
            ret = -1;
            goto out;
        }
    } else {
281
        if (update_health_check_from_image(image_health_check, container_spec) != 0) {
O
overweight 已提交
282 283 284 285 286 287 288 289 290
            ret = -1;
            goto out;
        }
    }

out:
    return ret;
}

291
int oci_image_merge_config(imagetool_image *image_conf, container_config *container_spec)
O
overweight 已提交
292 293 294
{
    int ret = 0;

295
    if (image_conf == NULL || container_spec == NULL) {
O
overweight 已提交
296 297 298 299 300
        ERROR("Invalid input arguments");
        return -1;
    }

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

303
        if (oci_image_merge_env(image_conf->spec->config, container_spec) != 0) {
O
overweight 已提交
304 305 306 307
            ret = -1;
            goto out;
        }

308
        if (oci_image_merge_entrypoint(image_conf->spec->config, container_spec) != 0) {
O
overweight 已提交
309 310 311 312
            ret = -1;
            goto out;
        }

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

315
        // ignore volumes now
O
overweight 已提交
316 317
    }

318
    if (oci_image_merge_health_check(image_conf->healthcheck, container_spec) != 0) {
O
overweight 已提交
319 320 321 322 323 324 325 326
        ret = -1;
        goto out;
    }

out:
    return ret;
}