diff --git a/ggdeploymentd/src/component_manager.c b/ggdeploymentd/src/component_manager.c index 54520a877..1b91e8e31 100644 --- a/ggdeploymentd/src/component_manager.c +++ b/ggdeploymentd/src/component_manager.c @@ -95,10 +95,11 @@ bool resolve_component_version( // TODO: also check that the component region matches the expected region // (component store functionality) GGL_LOGI( - "Found local candidate for %s that satisfies version requirements. " + "Found local candidate for %.*s that satisfies version requirements. " "Using " "the local candidate as the resolved version " "without negotiating with the cloud.", + (int) component_name.len, (char *) component_name.data ); diff --git a/ggdeploymentd/src/deployment_handler.c b/ggdeploymentd/src/deployment_handler.c index 37060c221..c47114785 100644 --- a/ggdeploymentd/src/deployment_handler.c +++ b/ggdeploymentd/src/deployment_handler.c @@ -46,6 +46,7 @@ #define MAX_RECIPE_BUF_SIZE 256000 #define MAX_DECODE_BUF_LEN 4096 +#define MAX_COMP_NAME_BUF_SIZE 10000 static struct DeploymentConfiguration { char data_endpoint[128]; @@ -1973,6 +1974,9 @@ static void handle_deployment( } GGL_CLEANUP(ggl_free_digest, digest_context); + static GglBuffer comp_name_buf[MAX_COMP_NAME_BUF_SIZE]; + GglBufVec comp_name_vec = GGL_BUF_VEC(comp_name_buf); + GGL_MAP_FOREACH(pair, resolved_components_kv_vec.map) { int component_artifacts_fd = -1; open_component_artifacts_dir( @@ -2234,32 +2238,147 @@ static void handle_deployment( // TODO: add install file processing logic here. if (component_updated) { - static uint8_t service_file_path_buf[PATH_MAX]; - GglByteVec service_file_path_vec - = GGL_BYTE_VEC(service_file_path_buf); - ret = ggl_byte_vec_append( - &service_file_path_vec, GGL_STR("ggl.") - ); - ggl_byte_vec_chain_append( - &ret, &service_file_path_vec, pair->key - ); - ggl_byte_vec_chain_append( - &ret, &service_file_path_vec, GGL_STR(".service") - ); + ret = ggl_buf_vec_push(&comp_name_vec, pair->key); if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to create service file path."); + GGL_LOGE("Failed to add the component name into vector"); return; } + } + } + if (comp_name_vec.buf_list.len == 0) { + GGL_LOGE("Failed to retrieve any component name"); + return; + } + + for (size_t i = 0; i < comp_name_vec.buf_list.len; i++) { + // install + static uint8_t install_service_file_path_buf[PATH_MAX]; + GglByteVec install_service_file_path_vec + = GGL_BYTE_VEC(install_service_file_path_buf); + ret = ggl_byte_vec_append( + &install_service_file_path_vec, args->root_path + ); + ggl_byte_vec_append(&install_service_file_path_vec, GGL_STR("/")); + ggl_byte_vec_append( + &install_service_file_path_vec, GGL_STR("ggl.") + ); + ggl_byte_vec_chain_append( + &ret, + &install_service_file_path_vec, + comp_name_vec.buf_list.bufs[i] + ); + ggl_byte_vec_chain_append( + &ret, + &install_service_file_path_vec, + GGL_STR(".install.service") + ); + if (ret == GGL_ERR_OK) { + // check if the current component name has relevant install + // service file created + int fd = -1; + ret = ggl_file_open( + install_service_file_path_vec.buf, O_RDONLY, 0, &fd + ); + if (ret != GGL_ERR_OK) { + GGL_LOGW( + "Component %.*s does not have the relevant install " + "service file", + (int) comp_name_vec.buf_list.bufs[i].len, + comp_name_vec.buf_list.bufs[i].data + ); + } else { // relevant install service file exists + + // run link command + static uint8_t link_command_buf[PATH_MAX]; + GglByteVec link_command_vec + = GGL_BYTE_VEC(link_command_buf); + ret = ggl_byte_vec_append( + &link_command_vec, GGL_STR("sudo systemctl link ") + ); + ggl_byte_vec_chain_append( + &ret, + &link_command_vec, + install_service_file_path_vec.buf + ); + ggl_byte_vec_chain_push(&ret, &link_command_vec, '\0'); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to create systemctl link command."); + return; + } + + // NOLINTNEXTLINE(concurrency-mt-unsafe) + int system_ret = system((char *) link_command_vec.buf.data); + if (WIFEXITED(system_ret)) { + if (WEXITSTATUS(system_ret) != 0) { + GGL_LOGE("systemctl link failed"); + return; + } + GGL_LOGI( + "systemctl link exited with child status %d\n", + WEXITSTATUS(system_ret) + ); + } else { + GGL_LOGE("systemctl link did not exit normally"); + return; + } + + // run start command + static uint8_t start_command_buf[PATH_MAX]; + GglByteVec start_command_vec + = GGL_BYTE_VEC(start_command_buf); + ret = ggl_byte_vec_append( + &start_command_vec, GGL_STR("sudo systemctl start ") + ); + ggl_byte_vec_chain_append( + &ret, + &start_command_vec, + install_service_file_path_vec.buf + ); + ggl_byte_vec_chain_push(&ret, &start_command_vec, '\0'); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to create systemctl start command."); + return; + } + + // NOLINTNEXTLINE(concurrency-mt-unsafe) + system_ret = system((char *) start_command_vec.buf.data); + if (WIFEXITED(system_ret)) { + if (WEXITSTATUS(system_ret) != 0) { + GGL_LOGE("systemctl start failed"); + return; + } + GGL_LOGI( + "systemctl start exited with child status %d\n", + WEXITSTATUS(system_ret) + ); + } else { + GGL_LOGE("systemctl start did not exit normally"); + return; + } + } + } + + // run or startup + static uint8_t service_file_path_buf[PATH_MAX]; + GglByteVec service_file_path_vec + = GGL_BYTE_VEC(service_file_path_buf); + ret = ggl_byte_vec_append(&service_file_path_vec, args->root_path); + ggl_byte_vec_append(&service_file_path_vec, GGL_STR("/")); + ggl_byte_vec_append(&service_file_path_vec, GGL_STR("ggl.")); + ggl_byte_vec_chain_append( + &ret, &service_file_path_vec, comp_name_vec.buf_list.bufs[i] + ); + ggl_byte_vec_chain_append( + &ret, &service_file_path_vec, GGL_STR(".service") + ); + if (ret == GGL_ERR_OK) { + // run link command static uint8_t link_command_buf[PATH_MAX]; GglByteVec link_command_vec = GGL_BYTE_VEC(link_command_buf); ret = ggl_byte_vec_append( &link_command_vec, GGL_STR("sudo systemctl link ") ); - ggl_byte_vec_chain_append( - &ret, &link_command_vec, args->root_path - ); - ggl_byte_vec_chain_push(&ret, &link_command_vec, '/'); ggl_byte_vec_chain_append( &ret, &link_command_vec, service_file_path_vec.buf ); @@ -2285,64 +2404,65 @@ static void handle_deployment( return; } - static uint8_t start_command_buf[PATH_MAX]; - GglByteVec start_command_vec = GGL_BYTE_VEC(start_command_buf); + // run enable command + static uint8_t enable_command_buf[PATH_MAX]; + GglByteVec enable_command_vec + = GGL_BYTE_VEC(enable_command_buf); ret = ggl_byte_vec_append( - &start_command_vec, GGL_STR("sudo systemctl start ") + &enable_command_vec, GGL_STR("sudo systemctl enable ") ); ggl_byte_vec_chain_append( - &ret, &start_command_vec, service_file_path_vec.buf + &ret, &enable_command_vec, service_file_path_vec.buf ); - ggl_byte_vec_chain_push(&ret, &start_command_vec, '\0'); + ggl_byte_vec_chain_push(&ret, &enable_command_vec, '\0'); if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to create systemctl start command."); + GGL_LOGE("Failed to create systemctl enable command."); return; } // NOLINTNEXTLINE(concurrency-mt-unsafe) - system_ret = system((char *) start_command_vec.buf.data); + system_ret = system((char *) enable_command_vec.buf.data); if (WIFEXITED(system_ret)) { if (WEXITSTATUS(system_ret) != 0) { - GGL_LOGE("systemctl start failed"); + GGL_LOGE("systemctl enable failed"); return; } GGL_LOGI( - "systemctl start exited with child status %d\n", + "systemctl enable exited with child status %d\n", WEXITSTATUS(system_ret) ); } else { - GGL_LOGE("systemctl start did not exit normally"); + GGL_LOGE("systemctl enable did not exit normally"); return; } - static uint8_t enable_command_buf[PATH_MAX]; - GglByteVec enable_command_vec - = GGL_BYTE_VEC(enable_command_buf); + // run daemon-reload command + static uint8_t reload_command_buf[PATH_MAX]; + GglByteVec reload_command_vec + = GGL_BYTE_VEC(reload_command_buf); ret = ggl_byte_vec_append( - &enable_command_vec, GGL_STR("sudo systemctl enable ") + &reload_command_vec, + GGL_STR("sudo systemctl daemon-reload\0") ); - ggl_byte_vec_chain_append( - &ret, &enable_command_vec, service_file_path_vec.buf - ); - ggl_byte_vec_chain_push(&ret, &enable_command_vec, '\0'); if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to create systemctl enable command."); + GGL_LOGE("Failed to create systemctl daemon-reload command." + ); return; } // NOLINTNEXTLINE(concurrency-mt-unsafe) - system_ret = system((char *) enable_command_vec.buf.data); + system_ret = system((char *) reload_command_vec.buf.data); if (WIFEXITED(system_ret)) { if (WEXITSTATUS(system_ret) != 0) { - GGL_LOGE("systemctl enable failed"); + GGL_LOGE("systemctl daemon-reload failed"); return; } GGL_LOGI( - "systemctl enable exited with child status %d\n", + "systemctl daemon-reload exited with child status %d\n", WEXITSTATUS(system_ret) ); } else { - GGL_LOGE("systemctl enable did not exit normally"); + GGL_LOGE("systemctl daemon-reload did not exit normally"); return; } } diff --git a/ggl-recipe/src/recipe.c b/ggl-recipe/src/recipe.c index 6353de7ac..9c3d3fc38 100644 --- a/ggl-recipe/src/recipe.c +++ b/ggl-recipe/src/recipe.c @@ -131,7 +131,8 @@ static GglError manifest_selection( // Check if the current OS supported first if ((strncmp((char *) os->buf.data, "linux", os->buf.len) == 0 - || strncmp((char *) os->buf.data, "*", os->buf.len) == 0)) { + || strncmp((char *) os->buf.data, "*", os->buf.len) == 0) + || strncmp((char *) os->buf.data, "all", os->buf.len) == 0) { // Then check if architecture is also supported if (((architecture_obj == NULL) || (architecture_obj->buf.len == 0) @@ -202,13 +203,11 @@ GglError select_linux_manifest( return ret; } - if (selected_lifecycle_object == NULL) { - GGL_LOGE("No lifecycle was found for linux"); - return GGL_ERR_FAILURE; - } - // If a lifecycle is successfully selected then look no futher - if (selected_lifecycle_object->type == GGL_TYPE_MAP) { - break; + if (selected_lifecycle_object != NULL) { + // If a lifecycle is successfully selected then look no futher + if (selected_lifecycle_object->type == GGL_TYPE_MAP) { + break; + } } } diff --git a/recipe2unit-test/CMakeLists.txt b/recipe2unit-test/CMakeLists.txt index b1a297f17..5172e06f0 100644 --- a/recipe2unit-test/CMakeLists.txt +++ b/recipe2unit-test/CMakeLists.txt @@ -2,4 +2,4 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -ggl_init_module(recipe2unit-test LIBS ggl-lib recipe2unit) +ggl_init_module(recipe2unit-test LIBS ggl-file ggl-lib recipe2unit) diff --git a/recipe2unit-test/src/entry.c b/recipe2unit-test/src/entry.c index 7245dfa14..61dbd9817 100644 --- a/recipe2unit-test/src/entry.c +++ b/recipe2unit-test/src/entry.c @@ -4,20 +4,36 @@ #include "ggl/recipe2unit.h" #include "recipe2unit-test.h" +#include #include #include #include +#include +#include #include #include +#include #include +// For the testing purpose, move the sample recipe.yml to /run/packages/recipes +// and rename it to recipe-1.0.0.yml + GglError run_recipe2unit_test(void) { static Recipe2UnitArgs args = { 0 }; - char component_name[] = "recipe.yml"; + char component_name[] = "recipe"; char version[] = "1.0.0"; char root_dir[] = "."; char recipe_runner_path[] = "/home/reciperunner"; + int root_path_fd; + GglError ret + = ggl_dir_open(GGL_STR(root_dir), O_PATH, false, &root_path_fd); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to open root dir."); + return ret; + } + args.root_path_fd = root_path_fd; + GglBuffer component_name_buff = (GglBuffer) { (uint8_t *) component_name, strlen(component_name) }; GglBuffer version_buff diff --git a/recipe2unit/src/parser.c b/recipe2unit/src/parser.c index 261b47f37..7a8c9abc8 100644 --- a/recipe2unit/src/parser.c +++ b/recipe2unit/src/parser.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -77,12 +78,14 @@ GglError convert_to_unit( recipe_obj ); if (ret != GGL_ERR_OK) { + GGL_LOGI("No recipe found"); return ret; } - static uint8_t install_unit_file_buffer[MAX_UNIT_FILE_BUF_SIZE]; // Note: currently, if we have both run and startup phases, - // we will only select startup for the script and unit file + // we will only select startup for the script and service file + static uint8_t install_unit_file_buffer[MAX_UNIT_FILE_BUF_SIZE]; + static uint8_t run_startup_unit_file_buffer[MAX_UNIT_FILE_BUF_SIZE]; GglBuffer install_response_buffer = (GglBuffer) { .data = (uint8_t *) install_unit_file_buffer, @@ -111,6 +114,10 @@ GglError convert_to_unit( ret = create_unit_file( args, component_name, is_install, &install_response_buffer ); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to create the install unit file."); + return ret; + } } ret = generate_systemd_unit( @@ -129,6 +136,10 @@ GglError convert_to_unit( ret = create_unit_file( args, component_name, is_install, &run_startup_response_buffer ); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to create the run or startup unit file."); + return ret; + } } return GGL_ERR_OK; diff --git a/recipe2unit/src/unit_file_generator.c b/recipe2unit/src/unit_file_generator.c index bc5dbe71e..adb124d6b 100644 --- a/recipe2unit/src/unit_file_generator.c +++ b/recipe2unit/src/unit_file_generator.c @@ -6,13 +6,10 @@ #include "file_operation.h" #include "ggl/recipe2unit.h" #include -#include #include -#include #include #include #include -#include #include #include #include @@ -32,10 +29,6 @@ #define MAX_RETRIES_INTERVAL_SECONDS "3600" #define RETRY_DELAY_SECONDS "1" -static GglError select_linux_manifest( - GglMap recipe_map, GglObject *val, GglMap *out_selected_lifecycle_map -); - static GglError concat_script_name_prefix_vec( const GglMap *recipe_map, GglByteVec *script_name_prefix_vec ); @@ -111,7 +104,7 @@ static GglError dependency_parser(GglObject *dependency_obj, GglByteVec *out) { } static GglError fill_unit_section( - GglMap recipe_map, GglByteVec *concat_unit_vector + GglMap recipe_map, GglByteVec *concat_unit_vector, PhaseSelection phase ) { GglObject *val; @@ -153,9 +146,11 @@ static GglError fill_unit_section( } } - if (ggl_map_get(recipe_map, GGL_STR("ComponentDependencies"), &val)) { - if ((val->type == GGL_TYPE_MAP) || (val->type == GGL_TYPE_LIST)) { - return dependency_parser(val, concat_unit_vector); + if (phase == RUN_STARTUP) { + if (ggl_map_get(recipe_map, GGL_STR("ComponentDependencies"), &val)) { + if ((val->type == GGL_TYPE_MAP) || (val->type == GGL_TYPE_LIST)) { + return dependency_parser(val, concat_unit_vector); + } } } @@ -237,7 +232,7 @@ static GglError fetch_script_section( return GGL_ERR_INVALID; } } else { - GGL_LOGE( + GGL_LOGW( "%.*s section is not in the lifecycle", (int) selected_phase.len, selected_phase.data @@ -432,99 +427,6 @@ static GglError update_unit_file_buffer( return GGL_ERR_OK; } -static GglError parse_install_section( - GglMap selected_lifecycle_map, - GglMap set_env_as_map, - char *root_dir, - GglMap *out_install_map, - GglAlloc *allocator -) { - GglObject *install_section; - if (ggl_map_get( - selected_lifecycle_map, GGL_STR("install"), &install_section - )) { - if (install_section->type != GGL_TYPE_MAP) { - GGL_LOGE("install section isn't formatted correctly"); - return GGL_ERR_INVALID; - } - - GglBuffer selected_script = { 0 }; - bool is_root = false; - GglError ret = fetch_script_section( - selected_lifecycle_map, - GGL_STR("install"), - &is_root, - &selected_script, - &set_env_as_map - ); - if (ret != GGL_ERR_OK) { - return ret; - } - static uint8_t mem[PATH_MAX]; - GglByteVec socketpath_vec = GGL_BYTE_VEC(mem); - ret = ggl_byte_vec_append( - &socketpath_vec, - (GglBuffer) { (uint8_t *) root_dir, strlen(root_dir) } - ); - ggl_byte_vec_chain_append( - &ret, &socketpath_vec, GGL_STR("/gg-ipc.socket") - ); - - GglObject out_object = GGL_OBJ_MAP(GGL_MAP( - { GGL_STR("requiresprivilege"), GGL_OBJ_BOOL(is_root) }, - { GGL_STR("script"), GGL_OBJ_BUF(selected_script) }, - { GGL_STR("set_env"), GGL_OBJ_MAP(set_env_as_map) }, - { GGL_STR("AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT"), - GGL_OBJ_BUF(socketpath_vec.buf) } - )); - - ret = ggl_obj_deep_copy(&out_object, allocator); - if (ret != GGL_ERR_OK) { - return ret; - } - *out_install_map = out_object.map; - - } else { - GGL_LOGW("No install section found within the recipe"); - return GGL_ERR_FAILURE; - } - return GGL_ERR_OK; -} - -static GglError create_standardized_install_file( - GglByteVec script_name_prefix_vec, - GglMap standardized_install_map, - char *root_dir -) { - static uint8_t json_buf[MAX_SCRIPT_SIZE]; - GglBuffer install_json_payload = GGL_BUF(json_buf); - GglError ret = ggl_json_encode( - GGL_OBJ_MAP(standardized_install_map), &install_json_payload - ); - if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to encode JSON."); - return ret; - } - - static uint8_t script_name_buf[PATH_MAX - 1]; - GglByteVec script_name_vec = GGL_BYTE_VEC(script_name_buf); - ret = ggl_byte_vec_append(&script_name_vec, script_name_prefix_vec.buf); - ggl_byte_vec_chain_append(&ret, &script_name_vec, GGL_STR("install.json")); - if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to append script details to vector."); - return GGL_ERR_FAILURE; - } - - ret = write_to_file( - root_dir, script_name_vec.buf, install_json_payload, 0600 - ); - if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to create and write the script file."); - return ret; - } - return GGL_ERR_OK; -} - // TODO: Refactor it // NOLINTNEXTLINE(readability-function-cognitive-complexity) static GglError manifest_builder( @@ -802,7 +704,7 @@ GglError generate_systemd_unit( = { .buf = { .data = unit_file_buffer->data, .len = 0 }, .capacity = MAX_UNIT_SIZE }; - GglError ret = fill_unit_section(*recipe_map, &concat_unit_vector); + GglError ret = fill_unit_section(*recipe_map, &concat_unit_vector, phase); if (ret != GGL_ERR_OK) { return ret; }