diff --git a/.devcontainer/features/spacefx-dev/install.sh b/.devcontainer/features/spacefx-dev/install.sh old mode 100644 new mode 100755 diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 0000000..0cc554a --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1 @@ +disable=SC2154 \ No newline at end of file diff --git a/build/build_containerImage.sh b/build/build_containerImage.sh old mode 100644 new mode 100755 diff --git a/certs/registry/registry.spacefx.local.ssl.json b/certs/registry/registry.spacefx.local.ssl.json index 50183f0..e2cc745 100644 --- a/certs/registry/registry.spacefx.local.ssl.json +++ b/certs/registry/registry.spacefx.local.ssl.json @@ -7,8 +7,8 @@ "*.registry.spacefx.local:5000", "registry.spacefx.local:5000", "localhost:5000", - "core-registry.core.svc.cluster.local", - "core-registry.core.svc.cluster.local:5000" + "coresvc-registry.coresvc.svc.cluster.local", + "coresvc-registry.coresvc.svc.cluster.local:5000" ], "key": { "algo": "rsa", diff --git a/chart/templates/core_buildservice.yaml b/chart/templates/coresvc_buildservice.yaml similarity index 100% rename from chart/templates/core_buildservice.yaml rename to chart/templates/coresvc_buildservice.yaml diff --git a/chart/templates/core_fileserver.yaml b/chart/templates/coresvc_fileserver.yaml similarity index 100% rename from chart/templates/core_fileserver.yaml rename to chart/templates/coresvc_fileserver.yaml diff --git a/chart/templates/core_registry.yaml b/chart/templates/coresvc_registry.yaml similarity index 98% rename from chart/templates/core_registry.yaml rename to chart/templates/coresvc_registry.yaml index 6beb3cb..d0fd050 100644 --- a/chart/templates/core_registry.yaml +++ b/chart/templates/coresvc_registry.yaml @@ -11,7 +11,7 @@ metadata: spec: type: NodePort ports: - - name: core-registry + - name: {{ $serviceValues.repository }} port: {{ $serviceValues.targetPort }} targetPort: {{ $serviceValues.targetPort }} selector: diff --git a/chart/templates/core_switchboard.yaml b/chart/templates/coresvc_switchboard.yaml similarity index 97% rename from chart/templates/core_switchboard.yaml rename to chart/templates/coresvc_switchboard.yaml index 7b49ce2..1ee24aa 100644 --- a/chart/templates/core_switchboard.yaml +++ b/chart/templates/coresvc_switchboard.yaml @@ -55,7 +55,7 @@ spec: version: v1 metadata: - name: host - value: "amqp://{{ $serviceValues.appName }}.core:5672" + value: "amqp://{{ $serviceValues.appName }}.coresvc:5672" - name: autoAck value: true - name: deliveryMode diff --git a/chart/values.yaml b/chart/values.yaml index 86b6c85..3b799b9 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -9,7 +9,7 @@ global: resourceScavengerTimingMS: 30000 containerCommand: dotnet containerRegistry: registry.spacefx.local:5000 - containerRegistryInternal: core-registry.core.svc.cluster.local:5000 + containerRegistryInternal: coresvc-registry.coresvc.svc.cluster.local:5000 dapr: logLevel: debug debugShim: @@ -79,7 +79,7 @@ global: namespaces: enabled: false list: - - namespace: core + - namespace: coresvc - namespace: hostsvc - namespace: payload-app - namespace: platformsvc @@ -102,7 +102,7 @@ subcharts: services: core: buildservice: - serviceNamespace: core + serviceNamespace: coresvc enabled: false targetService: appName: exampleapp @@ -113,13 +113,13 @@ services: dockerFile: Dockerfile.svc contextDir: build/dotnet registry: - appName: core-registry + appName: coresvc-registry containerCommand: - /usr/bin/registry containerArgs: - serve - /etc/docker/registry/config.yml - serviceNamespace: core + serviceNamespace: coresvc prod: enabled: false hasBase: false @@ -127,7 +127,7 @@ services: enabled: false hasBase: false enabled: false - repository: core-registry + repository: coresvc-registry targetPort: 5000 tlsCertificate: /certs/registry.spacefx.local.crt tlsKey: /certs/registry.spacefx.local.key @@ -139,8 +139,8 @@ services: limit: 1000m request: 10m switchboard: - appName: core-switchboard - serviceNamespace: core + appName: coresvc-switchboard + serviceNamespace: coresvc prod: enabled: true hasBase: false @@ -148,14 +148,14 @@ services: enabled: true hasBase: false enabled: false - repository: core-switchboard + repository: coresvc-switchboard fileserver: - appName: core-fileserver + appName: coresvc-fileserver logLevel: info maximumNumberOfLogs: 15 pollingTimeSecs: 5 - repository: core-fileserver - serviceNamespace: core + repository: coresvc-fileserver + serviceNamespace: coresvc prod: enabled: true hasBase: false diff --git a/modules/load_modules.sh b/modules/load_modules.sh index edcb302..49b0d5b 100755 --- a/modules/load_modules.sh +++ b/modules/load_modules.sh @@ -20,7 +20,8 @@ source "${MODULE_DIR}/m_40_regctl_config.sh" source "${MODULE_DIR}/m_45_emulator.sh" source "${MODULE_DIR}/m_50_spacefx-config.sh" source "${MODULE_DIR}/m_60_container_registries.sh" -source "${MODULE_DIR}/m_80_core_registry_hosts.sh" +source "${MODULE_DIR}/m_70_certificates.sh" +source "${MODULE_DIR}/m_80_coresvc_registry_hosts.sh" ############################################################ @@ -86,4 +87,4 @@ _app_prereqs_validate _generate_spacefx_config_json _update_regctl_config -_check_for_core_registry_hosts_entry +_check_for_coresvc_registry_hosts_entry diff --git a/modules/m_10_is_cmd_available.sh b/modules/m_10_is_cmd_available.sh old mode 100644 new mode 100755 diff --git a/modules/m_25_calculate_host_architecture.sh b/modules/m_25_calculate_host_architecture.sh old mode 100644 new mode 100755 diff --git a/modules/m_30_app_prereqs.sh b/modules/m_30_app_prereqs.sh old mode 100644 new mode 100755 diff --git a/modules/m_40_regctl_config.sh b/modules/m_40_regctl_config.sh old mode 100644 new mode 100755 diff --git a/modules/m_45_emulator.sh b/modules/m_45_emulator.sh old mode 100644 new mode 100755 diff --git a/modules/m_50_spacefx-config.sh b/modules/m_50_spacefx-config.sh old mode 100644 new mode 100755 diff --git a/modules/m_5_base.sh b/modules/m_5_base.sh index de6449b..527513c 100755 --- a/modules/m_5_base.sh +++ b/modules/m_5_base.sh @@ -43,6 +43,7 @@ function run_a_script() { fi local log_enabled=true + local log_results_enabled=true local ignore_error=false local run_in_background=false local returnResult="" @@ -59,6 +60,9 @@ function run_a_script() { --disable_log) log_enabled=false ;; + --no_log_results) + log_results_enabled=false + ;; --background) run_in_background=true ;; @@ -132,7 +136,7 @@ function run_a_script() { if [[ -n ${__returnVar} ]]; then returnResult=$(<"$script_temp_file") eval $__returnVar="'$returnResult'" - [[ "${log_enabled}" == true ]] && debug_log "...'${run_cmd}' Result: ${returnResult}" + [[ "${log_enabled}" == true ]] && [[ "${log_results_enabled}" == true ]] && debug_log "...'${run_cmd}' Result: ${returnResult}" fi if [[ $RETURN_CODE -gt 0 ]] && [[ "${ignore_error}" == false ]]; then diff --git a/modules/m_60_container_registries.sh b/modules/m_60_container_registries.sh old mode 100644 new mode 100755 index 4c930da..3970c63 --- a/modules/m_60_container_registries.sh +++ b/modules/m_60_container_registries.sh @@ -1,17 +1,108 @@ #!/bin/bash ############################################################ -# Find the first container registry with push access enabled +# Check if we need to add a prefix to the repo based on the supplied container registry ############################################################ -function get_registry_with_push_access() { - local return_result_var=$1 - if [[ -z "${return_result_var}" ]]; then - exit_with_error "Please supply a return variable name for results" +function check_for_repo_prefix(){ + + local registry="" + local repo="" + local returnResult="" + + while [[ "$#" -gt 0 ]]; do + case $1 in + --registry) + shift + registry=$1 + ;; + --repo) + shift + repo=$1 + ;; + --result) + shift + returnResult=$1 + ;; + *) + echo "Unknown parameter '$1'" + exit 1 + ;; + esac + shift + done + + if [[ -z "${container_registry}" ]] || [[ -z "${repo}" ]] || [[ -z "${returnResult}" ]]; then + exit_with_error "Missing a parameter. Please use function like check_for_repo_prefix --registry \"registry\" --repo \"repo\" --result \"returnResult\". Please supply all parameters." fi - run_a_script "jq -r '.config.containerRegistries[] | select(.push_enabled == true) | .url' ${SPACEFX_DIR}/tmp/config/spacefx-config.json | head -n 1" container_registry_with_push_access --ignore_error --disable_log - eval "$return_result_var='$container_registry_with_push_access'" + + if [[ ! -f "${SPACEFX_DIR}/tmp/config/spacefx-config.json" ]]; then + warn_log "Configuration file not found. Running '_generate_spacefx_config_json' to generate it." + _generate_spacefx_config_json + fi + + # Check if our destination repo has a repositoryPrefix + run_a_script "jq -r '.config.containerRegistries[] | select(.url == \"${registry}\") | if (has(\"repositoryPrefix\")) then .repositoryPrefix else \"\" end' ${SPACEFX_DIR}/tmp/config/spacefx-config.json" repo_prefix + + if [[ -n "${repo_prefix}" ]]; then + # Check if we already prefixed the repo name + if [[ "${repo}" == "$repo_prefix"* ]]; then + debug_log "Repository Prefix '${repo_prefix}' for ${registry} is already applied to '${repo}'. Nothing to do" + eval "$returnResult='${repo}'" + else + debug_log "Repository Prefix '${repo_prefix}' found for ${registry}. Returning '${repo_prefix}/${repo}'" + eval "$returnResult='${repo_prefix}/${repo}'" + fi + else + debug_log "No Repository Prefix found for ${registry}. Returning '${repo}'" + eval "$returnResult='${repo}'" + fi + +} + + +############################################################ +# Get the container tag value based on the channel we're using +############################################################ +function calculate_tag_from_channel() { + + local tag="" + local returnResult="" + local return_tag="" + + while [[ "$#" -gt 0 ]]; do + case $1 in + --tag) + shift + tag=$1 + ;; + --result) + shift + returnResult=$1 + ;; + *) + echo "Unknown parameter '$1'" + exit 1 + ;; + esac + shift + done + + if [[ -z "${tag}" ]] || [[ -z "${returnResult}" ]]; then + exit_with_error "Missing a parameter. Please use function like calculate_tag_from_channel --tag \"tag\" --result \"result\". Please supply all parameters." + fi + + if [[ "${SPACEFX_CHANNEL}" == "nightly" ]]; then + return_tag="${tag}-nightly" + fi + + if [[ "${SPACEFX_CHANNEL}" == "rc" ]]; then + return_tag="${tag}-rc" + fi + + eval "$returnResult='$return_tag'" } + ############################################################ # Find the first container registry with push access enabled ############################################################ @@ -43,13 +134,14 @@ function find_registry_for_image(){ for row in $container_registries; do parse_json_line --json "${row}" --property ".url" --result container_registry - info_log "Checking container registry '${container_registry}' for image '${container_image}'..." + check_for_repo_prefix --registry "${container_registry}" --repo "${container_image}" --result _find_registry_for_image_repo + + info_log "Checking container registry '${container_registry}' for image '${_find_registry_for_image_repo}'..." - login_to_container_registry ${container_registry} - run_a_script "regctl image manifest ${container_registry}/${container_image}" --ignore_error --disable_log + run_a_script "regctl image manifest ${container_registry}/${_find_registry_for_image_repo}" --ignore_error --disable_log if [[ "${RETURN_CODE}" -eq 0 ]]; then - info_log "...image '${container_image}' FOUND in container registry '${container_registry}'" + info_log "...image '${container_image}' FOUND in container registry '${container_registry}' as '${_find_registry_for_image_repo}'" REGISTRY_IMAGE_NAME="${container_registry}" break; else diff --git a/modules/m_70_certificates.sh b/modules/m_70_certificates.sh new file mode 100755 index 0000000..caa52c2 --- /dev/null +++ b/modules/m_70_certificates.sh @@ -0,0 +1,193 @@ +#!/bin/bash + +############################################################ +# Check if the root CA cert is available and if not, create it +############################################################ +function check_and_create_certificate_authority() { + # shellcheck disable=SC2154 + if [[ -f "${SPACEFX_DIR}/certs/ca/ca.spacefx.local.pem" ]]; then + if [[ ! -f "${SPACEFX_DIR}/certs/ca/ca.spacefx.local.crt" ]]; then + run_a_script "ln -sf ${SPACEFX_DIR}/certs/ca/ca.spacefx.local.pem ${SPACEFX_DIR}/certs/ca/ca.spacefx.local.crt" + fi + deploy_ca_cert_to_host + return + fi + + info_log "Generating '${SPACEFX_DIR}/certs/ca/ca.spacefx.local.pem'..." + + create_directory "${SPACEFX_DIR}/certs/ca" + + cd "${SPACEFX_DIR}/certs/ca" || exit_with_error "Failed to cd to '${SPACEFX_DIR}/certs/ca'" + + run_a_script "cfssl gencert -initca ${SPACEFX_DIR}/certs/ca/ca.spacefx.json | cfssljson -bare ca.spacefx.local" --no_log_results + + cd - || exit_with_error "Failed to cd back" + + run_a_script "mv ${SPACEFX_DIR}/certs/ca/ca.spacefx.local-key.pem ${SPACEFX_DIR}/certs/ca/ca.spacefx.local.key" + + info_log "...successfully generated '${SPACEFX_DIR}/certs/ca/ca.spacefx.local.pem' and '${SPACEFX_DIR}/certs/ca/ca.spacefx.local.key'" + + info_log "...removing old certificates that wasn't signed by the new ca..." + + while read -r certFile; do + if [[ "${certFile}" != "${SPACEFX_DIR}/certs/ca/ca.spacefx.local.pem" ]]; then + debug_log "Removing cert '${certFile}'..." + run_a_script "rm ${certFile}" + debug_log "...successfully removed '${certFile}'" + fi + done < <(find "${SPACEFX_DIR}/certs" -name "*.crt" -o -name "*.pem") + + run_a_script "ln -sf ${SPACEFX_DIR}/certs/ca/ca.spacefx.local.pem ${SPACEFX_DIR}/certs/ca/ca.spacefx.local.crt" + deploy_ca_cert_to_host +} + +############################################################ +# Check if the certificate authority cert is in authorized certificate authorities for the host +############################################################ +function deploy_ca_cert_to_host() { + # shellcheck disable=SC2154 + if [[ -f "/usr/local/share/ca-certificates/ca.spacefx.local/ca.spacefx.local.crt" ]]; then + if [[ ! -f "/etc/ssl/certs/ca.spacefx.local.pem" ]]; then + run_a_script "ln -sf ${SPACEFX_DIR}/certs/ca/ca.spacefx.local.pem /etc/ssl/certs/ca.spacefx.local.pem" + fi + is_cmd_available "update-ca-certificates" has_cmd + if [[ "${has_cmd}" == true ]]; then + run_a_script "update-ca-certificates" + fi + return + fi + + info_log "Deploying '${SPACEFX_DIR}/certs/ca/ca.spacefx.local.pem' to host..." + create_directory "/usr/local/share/ca-certificates/ca.spacefx.local" + + run_a_script "ln -sf ${SPACEFX_DIR}/certs/ca/ca.spacefx.local.crt /usr/local/share/ca-certificates/ca.spacefx.local/ca.spacefx.local.crt" + run_a_script "ln -sf ${SPACEFX_DIR}/certs/ca/ca.spacefx.local.pem /etc/ssl/certs/ca.spacefx.local.pem" + + info_log "...adding cert..." + + # Doing it this way lets us add to the host's chain incase we don't have update-ca-certificates + run_a_script "cat ${SPACEFX_DIR}/certs/ca/ca.spacefx.local.crt" space_fx_ca_cert + run_a_script "cat /etc/ssl/certs/ca-certificates.crt" current_ca_certs + + run_a_script "tee /etc/ssl/certs/ca-certificates.crt > /dev/null << SPACEFX_UPDATE_END +${current_ca_certs} +${space_fx_ca_cert} +SPACEFX_UPDATE_END" + + is_cmd_available "update-ca-certificates" has_cmd + if [[ "${has_cmd}" == true ]]; then + run_a_script "update-ca-certificates" + fi + + info_log "...successfully deployed '${SPACEFX_DIR}/certs/ca/ca.spacefx.local.pem' to host..." + +} + +############################################################ +# Remove all certs. +############################################################ +function remove_all_certs() { + create_directory "${SPACEFX_DIR}/certs" + + debug_log "Removing all certifcate artifactes from '${SPACEFX_DIR}/certs'..." + + while read -r certFile; do + info_log "...removing '${certFile}'..." + run_a_script "rm ${certFile}" + info_log "...successfully removed '${certFile}'..." + done < <(find "${SPACEFX_DIR}/certs" -name "*.crt" -o -name "*.pem" -o -name "*.key" -o -name "*.csr") + + is_cmd_available "update-ca-certificates" has_cmd + + if [[ "${has_cmd}" == true ]]; then + run_a_script "update-ca-certificates" + fi + + debug_log "...successfully removed all certificate artifacts from '${SPACEFX_DIR}/certs'" +} + +############################################################ +# Create a certificate +############################################################ +function generate_certificate() { + check_and_create_certificate_authority + + local cert_profile="" + local cert_config="" + local output_dir="" + + while [[ "$#" -gt 0 ]]; do + case $1 in + --profile) + shift + cert_profile=$1 + ;; + --config) + shift + cert_config=$1 + ;; + --output) + shift + output_dir=$1 + # Removing the trailing slash if there is one + output_dir=${output_dir%/} + ;; + esac + shift + done + + if [[ -z "${cert_profile}" ]]; then + exit_with_error "Missing --profile parameter. Please use function like generate_certificate --profile 'some-profile.json' --config 'some-config.json' --output '${SPACEFX_DIR}/certs/etc'" + fi + + if [[ -z "${cert_config}" ]]; then + exit_with_error "Missing --config parameter. Please use function like generate_certificate --profile 'some-profile.json' --config 'some-config.json' --output '${SPACEFX_DIR}/certs/etc'" + fi + + if [[ -z "${output_dir}" ]]; then + exit_with_error "Missing --output parameter. Please use function like generate_certificate --profile 'some-profile.json' --config 'some-config.json' --output '${SPACEFX_DIR}/certs/etc'" + fi + + if [[ ! -f "${cert_profile}" ]]; then + exit_with_error "--profile value '${cert_profile}' not found. Please check that file '${cert_profile}' exists" + fi + + if [[ ! -f "${cert_config}" ]]; then + exit_with_error "--profile value '${cert_config}' not found. Please check that file '${cert_config}' exists" + fi + + run_a_script "jq -r '.CN' ${cert_profile}" cert_name --ignore_error + + if [[ -z "${cert_name}" ]]; then + exit_with_error "Unable to calculate CN from '${cert_profile}'. No CN found" + fi + + if [[ -f "${output_dir}/${cert_name}.pem" ]]; then + # Certificate already exists. Nothing to do. + if [[ ! -f "${output_dir}/${cert_name}.crt" ]]; then + run_a_script "cp ${output_dir}/${cert_name}.pem ${output_dir}/${cert_name}.crt" + fi + return + fi + + create_directory ${output_dir} + + if [[ -f "${output_dir}/${cert_name}.crt" ]]; then + debug_log "Removing out-of-date '${output_dir}/${cert_name}.crt'" + run_a_script "rm ${output_dir}/${cert_name}.crt" + debug_log "...successfully removed out-of-date '${output_dir}/${cert_name}.crt'" + fi + + info_log "Generating '${output_dir}/${cert_name}.pem'..." + + cd "${output_dir}" || exit_with_error "Failed to cd to '${output_dir}'" + + run_a_script "cfssl gencert -ca=${SPACEFX_DIR}/certs/ca/ca.spacefx.local.pem -ca-key=${SPACEFX_DIR}/certs/ca/ca.spacefx.local.key -config=${cert_config} -profile=server ${cert_profile} | cfssljson -bare ${cert_name}" --no_log_results + + cd - || exit_with_error "Failed to cd back" + + run_a_script "cp ${output_dir}/${cert_name}.pem ${output_dir}/${cert_name}.crt" + run_a_script "mv ${output_dir}/${cert_name}-key.pem ${output_dir}/${cert_name}.key" + + info_log "...successfully generated '${output_dir}/${cert_name}.pem' and '${output_dir}/${cert_name}.key'..." +} diff --git a/modules/m_80_core_registry_hosts.sh b/modules/m_80_coresvc_registry_hosts.sh old mode 100644 new mode 100755 similarity index 92% rename from modules/m_80_core_registry_hosts.sh rename to modules/m_80_coresvc_registry_hosts.sh index 00367bc..ecce393 --- a/modules/m_80_core_registry_hosts.sh +++ b/modules/m_80_coresvc_registry_hosts.sh @@ -3,7 +3,7 @@ ############################################################ # Add the hosts entry for core registry ############################################################ -function _check_for_core_registry_hosts_entry() { +function _check_for_coresvc_registry_hosts_entry() { run_a_script "cat /etc/hosts" current_etc_hosts --disable_log if [[ $current_etc_hosts == *"registry.spacefx.local"* ]]; then return diff --git a/scripts/coresvc_registry.sh b/scripts/coresvc_registry.sh new file mode 100755 index 0000000..89ab5af --- /dev/null +++ b/scripts/coresvc_registry.sh @@ -0,0 +1,221 @@ +#!/bin/bash +# +# Starts and stops coresvc-registry, which is used during staging, running via k3s, and running in docker. Will deploy to k3s if available, or fallback to docker +# +# Example Usage: +# +# "bash ./scripts/coresvc_registry.sh" + +# Load the modules and pass all the same parameters that we're passing here +# shellcheck disable=SC1091 +# shellcheck disable=SC2068 +source "$(dirname "$(realpath "$0")")/../modules/load_modules.sh" $@ + +############################################################ +# Script variables +############################################################ +START_REGISTRY=false +STOP_REGISTRY=false +HAS_DOCKER=false +HAS_K3S=false +DESTINATION_HOST="" +REGISTRY_REPO="" + +############################################################ +# Help # +############################################################ +function show_help() { + # Display Help + echo "Starts and stops coresvc-registry, which is used during staging, running via k3s, and running in docker. Will deploy to k3s if available, or fallback to docker." + echo + echo "Syntax: bash ./scripts/coresvc_registry.sh [--dev-environment]" + echo "options:" + echo "--start [OPTIONAL] Start the registry. Will be in docker when paired with --dev-environment. Otherwise will start in kubernetes" + echo "--stop [OPTIONAL] Stops the registry. Will be in docker when paired with --dev-environment. Otherwise will stop in kubernetes" + echo "--help | -h [OPTIONAL] Help script (this screen)" + echo + exit 1 +} + + +############################################################ +# Process the input options. +############################################################ +while [[ "$#" -gt 0 ]]; do + case $1 in + -h|--help) show_help ;; + --start) + START_REGISTRY=true + ;; + --stop) + STOP_REGISTRY=true + ;; + *) echo "Unknown parameter '$1'"; show_help ;; + esac + shift +done + + +############################################################ +# Check to make sure we're good to go for the registry in development +############################################################ +function check_prerequisites(){ + info_log "START: ${FUNCNAME[0]}" + + is_cmd_available "docker" HAS_DOCKER + is_cmd_available "kubectl" HAS_K3S + + if [[ "${HAS_K3S}" == true ]]; then + # if we have kubectl, then check if we have k3s + is_cmd_available "k3s" HAS_K3S + + if [[ "${HAS_K3S}" == true ]]; then + # We have k3s, so we need to check if it's running + run_a_script "pgrep \"k3s\"" k3s_status --ignore_error + + if [[ -z "${k3s_status}" ]]; then + # k3s is installed but not running + HAS_K3S=false + fi + fi + fi + + # shellcheck disable=SC2154 + if [[ "${HAS_DOCKER}" == true ]]; then + debug_log "Docker found." + DESTINATION_HOST="docker" + fi + + if [[ "${HAS_K3S}" == true ]]; then + debug_log "K3s found." + DESTINATION_HOST="k3s" + fi + + [[ ! -d "${SPACEFX_DIR}/registry/data" ]] && create_directory "${SPACEFX_DIR}/registry/data" + [[ ! -d "${SPACEFX_DIR}/certs/registry" ]] && create_directory "${SPACEFX_DIR}/certs/registry" + + debug_log "Calculating registry repository name..." + run_a_script "yq '.services.core.registry.repository' ${SPACEFX_DIR}/chart/values.yaml" REGISTRY_REPO + debug_log "...registry repository name calculated as '${REGISTRY_REPO}'" + + info_log "END: ${FUNCNAME[0]}" +} + +############################################################ +# Stop the registry +############################################################ +function stop_registry(){ + info_log "START: ${FUNCNAME[0]}" + + if [[ "${HAS_DOCKER}" == true ]]; then + info_log "Checking for ${REGISTRY_REPO} in Docker..." + run_a_script "docker container inspect ${REGISTRY_REPO} | jq '.[0].State.Status' -r" docker_status --ignore_error + + if [[ -n "${docker_status}" ]]; then + info_log "...found ${REGISTRY_REPO} in Docker. Stopping..." + run_a_script "docker remove --force ${REGISTRY_REPO}" + info_log "...successfully stopped ${REGISTRY_REPO} in Docker" + else + info_log "...${REGISTRY_REPO} is not running in Docker. Nothing to do" + fi + fi + + if [[ "${HAS_K3S}" == true ]]; then + info_log "Checking for ${REGISTRY_REPO} in K3s..." + #TODO: Add + # kubectl get pods -l app.kubernetes.io/instance=${REGISTRY_REPO} + fi + + info_log "END: ${FUNCNAME[0]}" +} + + +############################################################ +# Start the registry in k3s +############################################################ +function start_registry_k3s(){ + info_log "START: ${FUNCNAME[0]}" + + + + info_log "END: ${FUNCNAME[0]}" +} + + +############################################################ +# Start the registry in docker +############################################################ +function start_registry_docker(){ + info_log "START: ${FUNCNAME[0]}" + + # Calculate the image tag based on the channel and then check the registries to find it + info_log "Checking for '${REGISTRY_REPO}' in docker images..." + calculate_tag_from_channel --tag "${SPACEFX_VERSION}" --result spacefx_version_tag + find_registry_for_image "${REGISTRY_REPO}:${spacefx_version_tag}" coresvc_registry_parent + + if [[ -z "${coresvc_registry_parent}" ]]; then + exit_with_error "${REGISTRY_REPO}:${spacefx_version_tag} was not found in any configured containers with pull_enabled. Please check your access" + fi + + # We have our parent container registry. Check to see if it needs a repo suffix + check_for_repo_prefix --registry "${container_registry}" --repo "${REGISTRY_REPO}" --result _repo_name + + # Check to see if the image is already in docker + run_a_script "docker images --format '{{json .}}' --no-trunc | jq -r '. | select(.Repository == \"${coresvc_registry_parent}/${_repo_name}\" and .Tag == \"${spacefx_version_tag}\") | any'" has_docker_image --ignore_error + + if [[ "${has_docker_image}" == "true" ]]; then + info_log "...image ${coresvc_registry_parent}/${_repo_name}:${spacefx_version_tag} already exists in Docker. Nothing to do" + else + info_log "...image ${coresvc_registry_parent}/${_repo_name}:${spacefx_version_tag} not found in Docker. Pulling..." + run_a_script "docker pull ${coresvc_registry_parent}/${_repo_name}:${spacefx_version_tag}" + info_log "...successfully pulled ${coresvc_registry_parent}/${_repo_name}:${spacefx_version_tag} to Docker." + fi + + + info_log "Starting '${REGISTRY_REPO}'..." + run_a_script "docker run -d \ + -p 5000:5000 \ + -v ${SPACEFX_DIR}/registry/data:/var/lib/registry \ + -v ${SPACEFX_DIR}/certs/registry:/certs \ + -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.spacefx.local.crt \ + -e REGISTRY_HTTP_TLS_KEY=/certs/registry.spacefx.local.key -e \ + --restart=always \ + --name=${REGISTRY_REPO} ${coresvc_registry_parent}/${_repo_name}:${spacefx_version_tag}" + + info_log "...successfully started core-registry." + + info_log "END: ${FUNCNAME[0]}" +} + +function main() { + write_parameter_to_log START_REGISTRY + write_parameter_to_log STOP_REGISTRY + + check_prerequisites + + stop_registry + + if [[ "${START_REGISTRY}" == false ]]; then + info_log "------------------------------------------" + info_log "END: ${SCRIPT_NAME}" + return + fi + + write_parameter_to_log DESTINATION_HOST + info_log "Starting ${REGISTRY_REPO}" + + if [[ ! -f "${SPACEFX_DIR}/certs/registry/registry.spacefx.local.crt" ]]; then + info_log "Missing certificates detected. Generating certificates and restarting ${REGISTRY_REPO} (if applicable)" + + generate_certificate --profile "${SPACEFX_DIR}/certs/registry/registry.spacefx.local.ssl.json" --config "${SPACEFX_DIR}/certs/registry/registry.spacefx.local.ssl-config.json" --output "${SPACEFX_DIR}/certs/registry" + fi + + [[ "${DESTINATION_HOST}" == "docker" ]] && start_registry_docker + # [[ "${DESTINATION_HOST}" == "k3s" ]] && start_registry_k3s + + info_log "------------------------------------------" + info_log "END: ${SCRIPT_NAME}" +} + + +main \ No newline at end of file diff --git a/scripts/stage/stage_chart_dependencies.sh b/scripts/stage/stage_chart_dependencies.sh new file mode 100755 index 0000000..fae4af2 --- /dev/null +++ b/scripts/stage/stage_chart_dependencies.sh @@ -0,0 +1,163 @@ +#!/bin/bash +# +# Downloads the third-party apps used by the Azure Orbital Space SDK for use in an airgapped, non-internet connected environment. +# +# Example Usage: +# +# "bash ./scripts/stage/stage_3p_apps.sh [--architecture arm64 | amd64]" + +# Load the modules and pass all the same parameters that we're passing here +# shellcheck disable=SC1091 +# shellcheck disable=SC2068 +source "$(dirname "$(realpath "$0")")/../../modules/load_modules.sh" $@ + +############################################################ +# Script variables +############################################################ +DEST_STAGE_DIR="" + + +############################################################ +# Help # +############################################################ +function show_help() { + # Display Help + echo "Downloads the third-party apps used by the Azure Orbital Space SDK for use in an airgapped, non-internet connected environment." + echo + echo "Syntax: bash ./scripts/stage/stage_3p_apps.sh [--architecture arm64 | amd64]" + echo "options:" + echo "--architecture | -a [OPTIONAL] Change the target architecture for download (defaults to current architecture)" + echo "--help | -h [OPTIONAL] Help script (this screen)" + echo + exit 1 +} + + +############################################################ +# Process the input options. +############################################################ +while [[ "$#" -gt 0 ]]; do + case $1 in + -a | --architecture) + shift + ARCHITECTURE=$1 + ARCHITECTURE=${ARCHITECTURE,,} # Force to lowercase + if [[ ! "${ARCHITECTURE}" == "amd64" ]] && [[ ! "${ARCHITECTURE}" == "arm64" ]]; then + echo "--architecture must be 'amd64' or 'arm64'. '${ARCHITECTURE}' is not valid." + show_help + exit 1 + fi + ;; + -h|--help) show_help ;; + *) echo "Unknown parameter '$1'"; show_help ;; + esac + shift +done + +if [[ -z "${ARCHITECTURE}" ]]; then + case $(uname -m) in + x86_64) ARCHITECTURE="amd64" ;; + aarch64) ARCHITECTURE="arm64" ;; + esac +fi + +DEST_STAGE_DIR="${SPACEFX_DIR}/bin/${ARCHITECTURE}" + + +############################################################ +# Check and download k3s +############################################################ +function stage_k3s(){ + info_log "START: ${FUNCNAME[0]}" + + local k3s_uri_filename="k3s" + local url_encoded_k3s_vers="" + + # The k3s version has special characters that need to be URL encoded + url_encoded_k3s_vers=$(jq -rn --arg x "${VER_K3S:?}" '$x|@uri') + + if [[ "${ARCHITECTURE}" == "arm64" ]]; then + k3s_uri_filename="k3s-arm64" + fi + + # Download k3s + _app_install --app "k3s" --source "${DEST_STAGE_DIR}/k3s/${VER_K3S}/k3s" --url "https://github.com/k3s-io/k3s/releases/download/${url_encoded_k3s_vers}/${k3s_uri_filename}" --destination "${DEST_STAGE_DIR}/k3s/${VER_K3S}/k3s" + + # Download k3s install script + _app_install --app "k3s_install.sh" --source "${DEST_STAGE_DIR}/k3s/${VER_K3S}/k3s_install.sh" --url "https://get.k3s.io/" --destination "${DEST_STAGE_DIR}/k3s/${VER_K3S}/k3s_install.sh" + + # Download k3s airgap images + _app_install --app "k3s-airgap-images-${ARCHITECTURE}.tar.gz" --source "${SPACEFX_DIR}/images/${ARCHITECTURE}/k3s-airgap-images-${ARCHITECTURE}.tar.gz" --url "https://github.com/k3s-io/k3s/releases/download/${url_encoded_k3s_vers}/k3s-airgap-images-${ARCHITECTURE}.tar.gz" --destination "${SPACEFX_DIR}/images/${ARCHITECTURE}/k3s-airgap-images-${ARCHITECTURE}.tar.gz" + + # Download kubectl + _app_install --app "kubectl" --source "${DEST_STAGE_DIR}/kubectl/${VER_KUBECTL}/kubectl" --url "https://dl.k8s.io/release/${VER_KUBECTL}/bin/linux/${ARCHITECTURE}/kubectl" --destination "${DEST_STAGE_DIR}/kubectl/${VER_KUBECTL}/kubectl" + + info_log "FINISHED: ${FUNCNAME[0]}" +} + +############################################################ +# Check and download Helm +############################################################ +function stage_helm(){ + info_log "START: ${FUNCNAME[0]}" + + local destination="${DEST_STAGE_DIR}/helm/${VER_HELM}/helm" + local destination_dir="$(dirname ${destination})" + if [[ -f "${destination}" ]]; then + info_log "App 'helm' already downloaded to '${destination}'. Nothing to do" + return + fi + + # Helm has to be downloaded and untarred, so we run it explicitly + local tmp_filename="${destination_dir}/helm-${VER_HELM}-linux-${ARCHITECTURE}.tar.gz" + local download_uri="https://get.helm.sh/helm-${VER_HELM}-linux-${ARCHITECTURE}.tar.gz" + + create_directory "${destination_dir}" + + run_a_script "curl --silent --fail --create-dirs --output ${tmp_filename} -L ${download_uri}" + + info_log "...succesfully downloaded to '${tmp_filename}'. Extracting to '${destination_dir}'..." + + run_a_script "tar -xf '${tmp_filename}' --directory '${destination_dir}' linux-${ARCHITECTURE}/helm" + run_a_script "mv ${destination_dir}/linux-${ARCHITECTURE}/helm ${destination_dir}/helm" + run_a_script "rm ${destination_dir}/linux-${ARCHITECTURE} -rf" + run_a_script "rm ${tmp_filename}" + + run_a_script "chmod 0755 ${destination_dir}/helm" + + info_log "...successfully extracted helm to '${destination_dir}'" + + info_log "FINISHED: ${FUNCNAME[0]}" +} + + +function main() { + write_parameter_to_log ARCHITECTURE + write_parameter_to_log DEST_STAGE_DIR + + + # Download CFSSL, jq, yq, regctl + local VER_CFSSL_no_v="${VER_CFSSL:1}" + _app_install --app "cfssl" --source "${DEST_STAGE_DIR}/cfssl/${VER_CFSSL}/cfssl" --url "https://github.com/cloudflare/cfssl/releases/download/${VER_CFSSL}/cfssl_${VER_CFSSL_no_v}_linux_${ARCHITECTURE}" --destination "${DEST_STAGE_DIR}/cfssl/${VER_CFSSL}/cfssl" + _app_install --app "cfssljson" --source "${DEST_STAGE_DIR}/cfssl/${VER_CFSSL}/cfssljson" --url "https://github.com/cloudflare/cfssl/releases/download/${VER_CFSSL}/cfssl_${VER_CFSSL_no_v}_linux_${ARCHITECTURE}" --destination "${DEST_STAGE_DIR}/cfssl/${VER_CFSSL}/cfssljson" + + _app_install --app "jq" --source "${DEST_STAGE_DIR}/jq/${VER_JQ}/jq" --url "https://github.com/jqlang/jq/releases/download/jq-${VER_JQ:?}/jq-linux-${ARCHITECTURE:?}" --destination "${DEST_STAGE_DIR}/jq/${VER_JQ}/jq" + _app_install --app "yq" --source "${DEST_STAGE_DIR}/yq/${VER_YQ}/yq" --url "https://github.com/mikefarah/yq/releases/download/v${VER_YQ:?}/yq_linux_${ARCHITECTURE:?}" --destination "${DEST_STAGE_DIR}/yq/${VER_YQ}/yq" + _app_install --app "regctl" --source "${DEST_STAGE_DIR}/regctl/${VER_REGCTL}/regctl" --url "https://github.com/regclient/regclient/releases/download/${VER_REGCTL:?}/regctl-linux-${ARCHITECTURE:?}" --destination "${DEST_STAGE_DIR}/regctl/${VER_REGCTL}/regctl" + + # Download k3s, kubectl, the airgap images, and the install script + stage_k3s + + # Run helm last since it's not running in the background task + stage_helm + + # Wait for any background tasks to finish + _app_install_wait_for_background_processes + + + info_log "------------------------------------------" + info_log "END: ${SCRIPT_NAME}" +} + + +main \ No newline at end of file