# limitations under the License.
#
+
# Convert input string to a safe name for K8s resources
function safe_name() {
local INPUT="$1"
#######################################################################################
-
function generator_encrypted_secret_cloud_credentials() {
local CLOUD_CREDENTIALS_FILENAME="$1"
local SECRET_NAME="$2"
"${TARGET_FOLDER}"
}
+
function scale_nodegroup() {
local NODEGROUP_NAME="$1"
local NODEGROUP_KUSTOMIZATION_NAME="$2"
local BASE_TEMPLATES_PATH="${15:-"cloud-resources"}"
local MANIFEST_FILENAME="${16:-"${NODEGROUP_NAME}"}"
- # Is the provider type supported?
+ # Is the provider type supported?
local VALID_PROVIDERS=("eks" "aks" "gke")
CLUSTER_TYPE="${CLUSTER_TYPE,,}"
[[ ! ($(echo ${VALID_PROVIDERS[@]} | grep -w "${CLUSTER_TYPE}")) ]] && return 1
"${TARGET_FOLDER}"
}
+
# Delete nodegroup
function delete_nodegroup() {
local NODEGROUP_KUSTOMIZATION_NAME="$1"
local PROJECT_NAME="${3:-"${MGMT_PROJECT_NAME}"}"
local FLEET_REPO_DIR="${4:-"${FLEET_REPO_DIR}"}"
local MGMT_RESOURCES_DIR="${5:-"${MGMT_RESOURCES_DIR}"}"
-
local NODEGROUP_DIR="${MGMT_RESOURCES_DIR}/${CLUSTER_NAME}/${NODEGROUP_KUSTOMIZATION_NAME}"
-
# Delete node Kustomizations
rm -rf "${NODEGROUP_DIR}"
}
+
# TODO: Deprecated
# Create AKS cluster (without bootstrap)
function create_cluster_aks() {
local SW_CATALOGS_REPO_URL="$3"
local PROJECT_NAME="${4:-"${MGMT_PROJECT_NAME}"}"
local SW_CATALOGS_REPO_DIR="${5:-"${SW_CATALOGS_REPO_DIR}"}"
-
+ # Path for the source templates
+ local TEMPLATES="${6:-"${SW_CATALOGS_REPO_DIR}/cloud-resources/flux-remote-bootstrap/cluster-base/templates"}"
+
# Optional inputs:
# Paths for each profile in the Git repo
- local INFRA_CONTROLLERS_PATH="${6:-"${PROJECT_NAME}/infra-controller-profiles/${CLUSTER_KUSTOMIZATION_NAME}"}"
- local INFRA_CONFIGS_PATH="${7:-"${PROJECT_NAME}/infra-config-profiles/${CLUSTER_KUSTOMIZATION_NAME}"}"
- local MANAGED_RESOURCES_PATH="${8:-"${PROJECT_NAME}/managed-resources/${CLUSTER_KUSTOMIZATION_NAME}"}"
- local APPS_PATH="${9:-"${PROJECT_NAME}/app-profiles/${CLUSTER_KUSTOMIZATION_NAME}"}"
-
- # Path for the source templates
- local TEMPLATES="${SW_CATALOGS_REPO_DIR}/cloud-resources/flux-remote-bootstrap/cluster-base/templates"
+ local INFRA_CONTROLLERS_PATH="${7:-"${PROJECT_NAME}/infra-controller-profiles/${CLUSTER_KUSTOMIZATION_NAME}"}"
+ local INFRA_CONFIGS_PATH="${8:-"${PROJECT_NAME}/infra-config-profiles/${CLUSTER_KUSTOMIZATION_NAME}"}"
+ local MANAGED_RESOURCES_PATH="${9:-"${PROJECT_NAME}/managed-resources/${CLUSTER_KUSTOMIZATION_NAME}"}"
+ local APPS_PATH="${10:-"${PROJECT_NAME}/app-profiles/${CLUSTER_KUSTOMIZATION_NAME}"}"
# Generate
export CLUSTER_KUSTOMIZATION_NAME
local PRIVATE_KEY_NEW_CLUSTER="$1"
local PUBLIC_KEY_MGMT="$2"
local CLUSTER_AGE_SECRET_NAME="${3:-$(safe_name "sops-age-${CLUSTER_KUSTOMIZATION_NAME}")}"
+ local CLUSTER_AGE_SECRET_NAMESPACE="${4:-"managed-resources"}"
join_lists \
<(cat) \
echo "${PRIVATE_KEY_NEW_CLUSTER}" | \
grep -v '^#' | \
kubectl create secret generic "${CLUSTER_AGE_SECRET_NAME}" \
- --namespace=managed-resources \
+ --namespace="${CLUSTER_AGE_SECRET_NAMESPACE}" \
--from-file=agekey=/dev/stdin \
-o yaml --dry-run=client | \
encrypt_secret_from_stdin \
local CLUSTER_KUSTOMIZATION_NAME="${2:-$(safe_name ${CLUSTER_NAME})}"
local CLUSTER_AGE_SECRET_NAME="${3:-$(safe_name "sops-age-${CLUSTER_KUSTOMIZATION_NAME}")}"
local SW_CATALOGS_REPO_DIR="${4:-"${SW_CATALOGS_REPO_DIR}"}"
+ local BOOTSTRAP_KUSTOMIZATION_NAMESPACE="${5:-"managed-resources"}"
+ local CLUSTER_KUSTOMIZATION_NAMESPACE="${6:-"managed-resources"}"
+ local BOOTSTRAP_SECRET_NAMESPACE="${7:-"managed-resources"}"
# Paths and names for the templates
- local MANIFEST_FILENAME="${5:-"cluster-bootstrap-${CLUSTER_KUSTOMIZATION_NAME}.yaml"}"
- local TEMPLATES="${6:-"${SW_CATALOGS_REPO_DIR}/cloud-resources/flux-remote-bootstrap/bootstrap/templates"}"
- local TEMPLATE_MANIFEST_FILENAME="${7:-"remote-cluster-bootstrap.yaml"}"
+ local MANIFEST_FILENAME="${7:-"cluster-bootstrap-${CLUSTER_KUSTOMIZATION_NAME}.yaml"}"
+ local TEMPLATES="${8:-"${SW_CATALOGS_REPO_DIR}/cloud-resources/flux-remote-bootstrap/bootstrap/templates"}"
+ local TEMPLATE_MANIFEST_FILENAME="${9:-"remote-cluster-bootstrap.yaml"}"
+
+ # Variables for kubeconfig secret configuration
+ local CLUSTER_KUBECONFIG_SECRET_KEY=${CLUSTER_KUBECONFIG_SECRET_KEY:-"kubeconfig"}
+ local CLUSTER_KUBECONFIG_SECRET_NAME=${CLUSTER_KUBECONFIG_SECRET_NAME:-"kubeconfig-${CLUSTER_KUSTOMIZATION_NAME}"}
# Generate manifests
export CLUSTER_KUSTOMIZATION_NAME
export CLUSTER_NAME
export CLUSTER_AGE_SECRET_NAME
+ export CLUSTER_KUBECONFIG_SECRET_KEY
+ export CLUSTER_KUBECONFIG_SECRET_NAME
+ export BOOTSTRAP_KUSTOMIZATION_NAMESPACE
+ export CLUSTER_KUSTOMIZATION_NAMESPACE
+ export BOOTSTRAP_SECRET_NAMESPACE
join_lists \
<(cat) \
"${TEMPLATE_MANIFEST_FILENAME}" \
"${MANIFEST_FILENAME}" | \
replace_env_vars \
- '${CLUSTER_KUSTOMIZATION_NAME},${CLUSTER_NAME},${CLUSTER_AGE_SECRET_NAME}'
+ '${CLUSTER_KUSTOMIZATION_NAME},${CLUSTER_NAME},${CLUSTER_AGE_SECRET_NAME},${CLUSTER_KUBECONFIG_SECRET_KEY},${CLUSTER_KUBECONFIG_SECRET_NAME},${CLUSTER_KUSTOMIZATION_NAMESPACE},${BOOTSTRAP_KUSTOMIZATION_NAMESPACE},${BOOTSTRAP_SECRET_NAMESPACE}'
)
}
local PUBLIC_KEY_NEW_CLUSTER="$9"
local PRIVATE_KEY_NEW_CLUSTER="${10:-${PRIVATE_KEY_NEW_CLUSTER}}"
local IMPORTED_CLUSTER="${11:-"false"}"
-
-
- # Calculates the folder where managed resources area defined
- local MGMT_RESOURCES_DIR="${FLEET_REPO_DIR}/${MGMT_PROJECT_NAME}/managed-resources/_management"
+ local MGMT_CLUSTER_NAME="${12:-"_management"}"
+ local CLUSTER_KUBECONFIG_SECRET_NAME=${13:-"kubeconfig-${CLUSTER_KUSTOMIZATION_NAME}"}
+ local CLUSTER_KUBECONFIG_SECRET_KEY=${14:-"kubeconfig"}
+ local TEMPLATES_DIR="${15:-"${SW_CATALOGS_REPO_DIR}/cloud-resources/flux-remote-bootstrap/cluster-base/templates"}"
+ local BOOTSTRAP_KUSTOMIZATION_NAMESPACE="${16:-"managed-resources"}"
+ local CLUSTER_KUSTOMIZATION_NAMESPACE="${17:-"managed-resources"}"
+ local BOOTSTRAP_SECRET_NAMESPACE="${18:-"${BOOTSTRAP_KUSTOMIZATION_NAMESPACE}"}"
+
+ # Calculates the folder where managed resources are defined
+ local MGMT_RESOURCES_DIR="${FLEET_REPO_DIR}/${MGMT_PROJECT_NAME}/managed-resources/${MGMT_CLUSTER_NAME}"
# Create profile folders
echo "" | \
"${FLEET_REPO_URL}" \
"${SW_CATALOGS_REPO_URL}" \
"${MGMT_PROJECT_NAME}" \
- "${SW_CATALOGS_REPO_DIR}" | \
+ "${SW_CATALOGS_REPO_DIR}" \
+ "${TEMPLATES_DIR}" | \
list2folder_cp_over \
"${CLUSTER_FOLDER}"
"${CLUSTER_NAME}" \
"${CLUSTER_KUSTOMIZATION_NAME}" \
"${CLUSTER_AGE_SECRET_NAME}" \
- "${SW_CATALOGS_REPO_DIR}" | \
+ "${SW_CATALOGS_REPO_DIR}" \
+ "${BOOTSTRAP_KUSTOMIZATION_NAMESPACE}" \
+ "${CLUSTER_KUSTOMIZATION_NAMESPACE}" \
+ "${BOOTSTRAP_SECRET_NAMESPACE}" | \
generator_k8s_age_secret_new_cluster \
"${PRIVATE_KEY_NEW_CLUSTER}" \
"${PUBLIC_KEY_MGMT}" \
- "${CLUSTER_AGE_SECRET_NAME}" | \
+ "${CLUSTER_AGE_SECRET_NAME}" \
+ "${BOOTSTRAP_SECRET_NAMESPACE}" | \
prepend_folder_path "${CLUSTER_KUSTOMIZATION_NAME}/" | \
list2folder_cp_over \
"${MGMT_RESOURCES_DIR}"
local TEMPLATE_MANIFEST_FILENAME="${26:-"${CLUSTER_TYPE,,}01.yaml"}"
local MANIFEST_FILENAME="${27:-"${CLUSTER_TYPE,,}-${CLUSTER_NAME}.yaml"}"
-
# Is the provider type supported?
local VALID_PROVIDERS=("eks" "aks" "gke")
CLUSTER_TYPE="${CLUSTER_TYPE,,}"
local PROJECT_NAME="${2:-"${MGMT_PROJECT_NAME}"}"
local FLEET_REPO_DIR="${3:-"${FLEET_REPO_DIR}"}"
local MGMT_RESOURCES_DIR="${4:-"${MGMT_RESOURCES_DIR}"}"
+ local MGMT_CLUSTER_DIR="${5:-"${MGMT_CLUSTER_DIR}"}"
# Optional inputs: Paths for each profile in the Git repo
- local INFRA_CONTROLLERS_DIR="${5:-"${FLEET_REPO_DIR}/${PROJECT_NAME}/infra-controller-profiles/${CLUSTER_KUSTOMIZATION_NAME}"}"
- local INFRA_CONFIGS_DIR="${6:-"${FLEET_REPO_DIR}/${PROJECT_NAME}/infra-config-profiles/${CLUSTER_KUSTOMIZATION_NAME}"}"
- local MANAGED_RESOURCES_DIR="${7:-"${FLEET_REPO_DIR}/${PROJECT_NAME}/managed-resources/${CLUSTER_KUSTOMIZATION_NAME}"}"
- local APPS_DIR="${8:-"${FLEET_REPO_DIR}/${PROJECT_NAME}/app-profiles/${CLUSTER_KUSTOMIZATION_NAME}"}"
- local CLUSTER_DIR="${9:-"${FLEET_REPO_DIR}/clusters/${CLUSTER_KUSTOMIZATION_NAME}"}"
+ local INFRA_CONTROLLERS_DIR="${6:-"${FLEET_REPO_DIR}/${PROJECT_NAME}/infra-controller-profiles/${CLUSTER_KUSTOMIZATION_NAME}"}"
+ local INFRA_CONFIGS_DIR="${7:-"${FLEET_REPO_DIR}/${PROJECT_NAME}/infra-config-profiles/${CLUSTER_KUSTOMIZATION_NAME}"}"
+ local MANAGED_RESOURCES_DIR="${8:-"${FLEET_REPO_DIR}/${PROJECT_NAME}/managed-resources/${CLUSTER_KUSTOMIZATION_NAME}"}"
+ local MGMT_CLUSTER_DIR="${9:-"${FLEET_REPO_DIR}/${PROJECT_NAME}/managed-resources/${MGMT_CLUSTER_DIR}"}"
+ local APPS_DIR="${10:-"${FLEET_REPO_DIR}/${PROJECT_NAME}/app-profiles/${CLUSTER_KUSTOMIZATION_NAME}"}"
+ local CLUSTER_DIR="${11:-"${FLEET_REPO_DIR}/clusters/${CLUSTER_KUSTOMIZATION_NAME}"}"
# Optional input: Do I need a purge operation first?
- local PURGE="${10:-"false"}"
+ local PURGE="${12:-"false"}"
# Perform the purge if needed
if [[ "${PURGE,,}" == "true" ]]; then
echo "Purging the remote Flux instalation..."
- flux uninstall -s --namespace=flux-system
fi
echo "Deleting cluster profiles and (when applicable) its cloud resources..."
rm -rf "${INFRA_CONTROLLERS_DIR}"
rm -rf "${INFRA_CONFIGS_DIR}"
rm -rf "${MANAGED_RESOURCES_DIR}"
+ rm -rf "${MGMT_CLUSTER_DIR}"
rm -rf "${APPS_DIR}"
# Delete base cluster Kustomizations
"${MANIFEST_FILENAME}"
}
+# Create remote CAPI cluster for Openstack
+function create_capi_openstack_cluster() {
+ local CLUSTER_KUSTOMIZATION_NAME="${1}"
+ local CLUSTER_NAME="${2}"
+ local VM_SIZE="${3}"
+ local VM_SIZE_CONTROL_PLANE="${4:-"${VM_SIZE}"}"
+ local NODE_COUNT="${5}"
+ local NODE_COUNT_CONTROLPLANE="${6:-"1"}"
+ local K8S_VERSION="${7}"
+ # OpenStack specific
+ local OPENSTACK_CLOUD_NAME="${8}"
+ local OPENSTACK_DNS_NAMESERVERS="${9}"
+ local OPENSTACK_EXTERNAL_NETWORK_ID="${10}"
+ local OPENSTACK_FAILURE_DOMAIN="${11}"
+ local OPENSTACK_SSH_KEY_NAME="${12}"
+ local CNI="${13:-"calico"}"
+ local OPENSTACK_WORKER_IMAGE_NAME="${14:-"osm-capo-node-${K8S_VERSION}"}"
+ local OPENSTACK_CONTROL_PLANE_IMAGE_NAME="${15:-"${OPENSTACK_WORKER_IMAGE_NAME}"}"
+ # SOPS-AGE related
+ local PUBLIC_KEY_MGMT="${16:-"${PUBLIC_KEY_MGMT}"}"
+ local PUBLIC_KEY_NEW_CLUSTER="${17:-"${PUBLIC_KEY_NEW_CLUSTER}"}"
+ local PRIVATE_KEY_NEW_CLUSTER="${18:-"${PRIVATE_KEY_NEW_CLUSTER}"}"
+ # GitOps retaled
+ local FLEET_REPO_DIR="${19:-"${FLEET_REPO_DIR}"}"
+ local FLEET_REPO_URL="${20:-"${FLEET_REPO_URL}"}"
+ local SW_CATALOGS_REPO_DIR="${21:-"${SW_CATALOGS_REPO_DIR}"}"
+ local SW_CATALOGS_REPO_URL="${22:-"${SW_CATALOGS_REPO_URL}"}"
+ local SKIP_BOOTSTRAP="${23:-"false"}"
+ local MGMT_PROJECT_NAME="${24:-"osm_admin"}"
+ local MGMT_CLUSTER_NAME="${25:-"_management"}"
+ local BASE_TEMPLATES_PATH="${26:-"cloud-resources/capi"}"
+ local NAMESPACE="${27:-"managed-resources"}"
+
+ # Varibles with valus from convention.
+ local CLUSTER_TYPE="openstack"
+ local TEMPLATE_MANIFEST_FILENAME="capi-cluster.yaml"
+ local MANIFEST_FILENAME="openstack-${CLUSTER_NAME}.yaml"
+ local CLOUD_CREDENTIALS="${OPENSTACK_CLOUD_NAME}-capo-config"
+
+ # Determines the source dir for the templates and the target folder in Fleet
+ local TEMPLATES_DIR="${SW_CATALOGS_REPO_DIR}/${BASE_TEMPLATES_PATH}/openstack-kubeadm/templates"
+ local TARGET_FOLDER="${FLEET_REPO_DIR}/${MGMT_PROJECT_NAME}/managed-resources/${MGMT_CLUSTER_NAME}"
+ export CNI=${CNI,,}
+
+ # Variables for kubeconfig secret reference
+ export CLUSTER_KUBECONFIG_SECRET_NAME="${CLUSTER_KUSTOMIZATION_NAME}-kubeconfig"
+ export CLUSTER_KUBECONFIG_SECRET_KEY="value"
+
+ export CLUSTER_KUSTOMIZATION_NAME
+ export OPENSTACK_CLOUD_NAME
+
+ folder2list \
+ "${TEMPLATES_DIR}" | \
+ replace_env_vars \
+ '${CLUSTER_KUSTOMIZATION_NAME},${CNI},${CLUSTER_KUBECONFIG_SECRET_NAME},${CLUSTER_KUBECONFIG_SECRET_KEY},${OPENSTACK_CLOUD_NAME}' | \
+ patch_replace \
+ ".spec.postBuild.substitute.cluster_name" \
+ "${CLUSTER_NAME}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.cni" \
+ "${CNI}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.control_plane_machine_count" \
+ "${NODE_COUNT_CONTROLPLANE}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.kubernetes_version" \
+ "v${K8S_VERSION}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.namespace" \
+ "${NAMESPACE}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.worker_machine_count" \
+ "${NODE_COUNT}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.openstack_cloud" \
+ "${OPENSTACK_CLOUD_NAME}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.openstack_cloud_conf" \
+ "${CLOUD_CREDENTIALS}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.openstack_control_plane_machine_flavor" \
+ "${VM_SIZE_CONTROL_PLANE}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.openstack_dns_nameservers" \
+ "${OPENSTACK_DNS_NAMESERVERS}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.openstack_external_network_id" \
+ "${OPENSTACK_EXTERNAL_NETWORK_ID}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.openstack_failure_domain" \
+ "${OPENSTACK_FAILURE_DOMAIN}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.openstack_worker_image_name" \
+ "${OPENSTACK_WORKER_IMAGE_NAME}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.openstack_control_plane_image_name" \
+ "${OPENSTACK_CONTROL_PLANE_IMAGE_NAME}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.openstack_node_machine_flavor" \
+ "${VM_SIZE}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.openstack_ssh_key_name" \
+ "${OPENSTACK_SSH_KEY_NAME}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ rename_file_in_items \
+ "${TEMPLATE_MANIFEST_FILENAME}" \
+ "${MANIFEST_FILENAME}" | \
+ prepend_folder_path "${CLUSTER_KUSTOMIZATION_NAME}/" | \
+ list2folder_cp_over \
+ "${TARGET_FOLDER}"
+
+ # Bootstrap (unless asked to skip)
+ if [[ "${SKIP_BOOTSTRAP,,}" == "true" ]]; then
+ return 0
+ fi
+
+ create_bootstrap_for_remote_cluster \
+ "${CLUSTER_NAME}" \
+ "${CLUSTER_KUSTOMIZATION_NAME}" \
+ "${FLEET_REPO_DIR}" \
+ "${SW_CATALOGS_REPO_DIR}" \
+ "${FLEET_REPO_URL}" \
+ "${SW_CATALOGS_REPO_URL}" \
+ "${MGMT_PROJECT_NAME}" \
+ "${PUBLIC_KEY_MGMT}" \
+ "${PUBLIC_KEY_NEW_CLUSTER}" \
+ "${PRIVATE_KEY_NEW_CLUSTER}" \
+ "false" \
+ '' \
+ "${CLUSTER_KUBECONFIG_SECRET_NAME}" \
+ "${CLUSTER_KUBECONFIG_SECRET_KEY}"
+
+}
+
+# Update remote CAPI cluster for Openstack
+function update_capi_openstack_cluster() {
+ local CLUSTER_KUSTOMIZATION_NAME="${1}"
+ local CLUSTER_NAME="${2}"
+ local VM_SIZE="${3}"
+ local VM_SIZE_CONTROL_PLANE="${4}"
+ local NODE_COUNT="${5}"
+ local NODE_COUNT_CONTROLPLANE="${6}"
+ local K8S_VERSION="${7}"
+ # OpenStack specific
+ local OPENSTACK_CLOUD_NAME="${8}"
+ local OPENSTACK_DNS_NAMESERVERS="${9}"
+ local OPENSTACK_EXTERNAL_NETWORK_ID="${10}"
+ local OPENSTACK_FAILURE_DOMAIN="${11}"
+ local OPENSTACK_SSH_KEY_NAME="${12}"
+ local CNI="${13:-"calico"}"
+ local OPENSTACK_WORKER_IMAGE_NAME="${14:-"osm-capo-node-${K8S_VERSION}"}"
+ local OPENSTACK_CONTROL_PLANE_IMAGE_NAME="${15:-"${OPENSTACK_WORKER_IMAGE_NAME}"}"
+ # SOPS-AGE related
+ local PUBLIC_KEY_MGMT="${16:-"${PUBLIC_KEY_MGMT}"}"
+ local PUBLIC_KEY_NEW_CLUSTER="${17:-"${PUBLIC_KEY_NEW_CLUSTER}"}"
+ local PRIVATE_KEY_NEW_CLUSTER="${18:-"${PRIVATE_KEY_NEW_CLUSTER}"}"
+ # GitOps retaled
+ local FLEET_REPO_DIR="${19:-"${FLEET_REPO_DIR}"}"
+ local FLEET_REPO_URL="${20:-"${FLEET_REPO_URL}"}"
+ local SW_CATALOGS_REPO_DIR="${21:-"${SW_CATALOGS_REPO_DIR}"}"
+ local SW_CATALOGS_REPO_URL="${22:-"${SW_CATALOGS_REPO_URL}"}"
+ local MGMT_PROJECT_NAME="${23:-"osm_admin"}"
+ local MGMT_CLUSTER_NAME="${24:-"_management"}"
+ local BASE_TEMPLATES_PATH="${25:-"cloud-resources/capi"}"
+ local NAMESPACE="${26:-"managed-resources"}"
+
+ # Determine key folders in Fleet
+ local MGMT_RESOURCES_DIR="${FLEET_REPO_DIR}/${MGMT_PROJECT_NAME}/managed-resources/${MGMT_CLUSTER_NAME}"
+
+ # Updating no new cluster
+ local SKIP_BOOTSTRAP="true"
+
+ create_capi_openstack_cluster \
+ "${CLUSTER_KUSTOMIZATION_NAME}" \
+ "${CLUSTER_NAME}" \
+ "${VM_SIZE}" \
+ "${VM_SIZE_CONTROL_PLANE}" \
+ "${NODE_COUNT}" \
+ "${NODE_COUNT_CONTROLPLANE}" \
+ "${K8S_VERSION}" \
+ "${OPENSTACK_CLOUD_NAME}" \
+ "${OPENSTACK_DNS_NAMESERVERS}" \
+ "${OPENSTACK_EXTERNAL_NETWORK_ID}" \
+ "${OPENSTACK_FAILURE_DOMAIN}" \
+ "${OPENSTACK_SSH_KEY_NAME}" \
+ "${CNI}" \
+ "${OPENSTACK_WORKER_IMAGE_NAME}" \
+ "${OPENSTACK_CONTROL_PLANE_IMAGE_NAME}" \
+ "${PUBLIC_KEY_MGMT}" \
+ "${PUBLIC_KEY_NEW_CLUSTER}" \
+ "${PRIVATE_KEY_NEW_CLUSTER}" \
+ "${FLEET_REPO_DIR}" \
+ "${FLEET_REPO_URL}" \
+ "${SW_CATALOGS_REPO_DIR}" \
+ "${SW_CATALOGS_REPO_URL}" \
+ "${SKIP_BOOTSTRAP}" \
+ "${MGMT_PROJECT_NAME}" \
+ "${MGMT_CLUSTER_NAME}" \
+ "${BASE_TEMPLATES_PATH}" \
+ "${NAMESPACE}"
+}
+
+# Create remote Openshift cluster via ACM
+function create_openshift_cluster {
+ local CLUSTER_KUSTOMIZATION_NAME="${1}"
+ local CLUSTER_NAME="${2}"
+ # This has to be void. Stored in database
+ local K8S_VERSION="${3:-"''"}"
+ # SOPS-AGE related
+ local PUBLIC_KEY_ACM="${4}"
+ local PUBLIC_KEY_NEW_CLUSTER="${5:-"${PUBLIC_KEY_NEW_CLUSTER}"}"
+ local PRIVATE_KEY_NEW_CLUSTER="${6:-"${PRIVATE_KEY_NEW_CLUSTER}"}"
+ # OpenShift
+ local OPENSHIFT_RELEASE="${7}"
+ local INFRA_PUBLIC_SSH_KEY="${8}"
+ local CONTROL_PLANE_AVAILABILITY="${9}"
+ local WORKER_COUNT="${10}"
+ local WORKER_CORES="${11}"
+ local WORKER_MEMORY="${12}"
+ local WORKER_VOLUME_SIZE="${13}"
+ local STORAGE_CLASS="${14}"
+ local BASE_DOMAIN="${15}"
+ local MGMT_CLUSTER_NAME="${16}"
+ local HOSTED_CLUSTERS_PROJECT="${17:-"clusters"}"
+ local ETCD_VOLUME_SIZE="${18:-"8"}"
+ # GitOps retaled
+ local FLEET_REPO_DIR="${19:-"${FLEET_REPO_DIR}"}"
+ local FLEET_REPO_URL="${20:-"${FLEET_REPO_URL}"}"
+ local SW_CATALOGS_REPO_DIR="${21:-"${SW_CATALOGS_REPO_DIR}"}"
+ local SW_CATALOGS_REPO_URL="${22:-"${SW_CATALOGS_REPO_URL}"}"
+ local SKIP_BOOTSTRAP="${23:-"false"}"
+ # Only change if absolutely needeed
+ local MGMT_PROJECT_NAME="${24:-"osm_admin"}"
+ local BASE_TEMPLATES_PATH="${25:-"cloud-resources"}"
+ local TEMPLATE_MANIFEST_FILENAME="${26:-"openshift01.yaml"}"
+ local MANIFEST_FILENAME="${27:-"openshift-${CLUSTER_NAME}.yaml"}"
+
+ local TEMPLATES_DIR="${SW_CATALOGS_REPO_DIR}/cloud-resources/openshift/templates"
+ local TARGET_FOLDER="${FLEET_REPO_DIR}/${MGMT_PROJECT_NAME}/managed-resources/${MGMT_CLUSTER_NAME}"
+
+ # Internally ACM creates several projects for each cluster.
+ # Specifically the klusterletaddonconfig must land in a project with the same name as the cluster.
+ # This will be specifically controlled by the variable `CLUSTER_PROJECT`.
+ #
+ # It must be notes that CLUSTER_NAME, CLUSTER_KUSTOMIZATION_NAME and CLUSTER_PROJECT have the same value,
+ # but they are conceptually different.
+ local CLUSTER_PROJECT="${CLUSTER_KUSTOMIZATION_NAME}"
+
+ export CLUSTER_KUSTOMIZATION_NAME
+
+ folder2list \
+ "${TEMPLATES_DIR}" | \
+ replace_env_vars \
+ '${CLUSTER_KUSTOMIZATION_NAME}' | \
+ patch_replace \
+ ".spec.postBuild.substitute.base_domain" \
+ "${BASE_DOMAIN}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.cluster_name" \
+ "${CLUSTER_NAME}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.cluster_project" \
+ "${CLUSTER_PROJECT}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.hosted_cluster_project" \
+ "${HOSTED_CLUSTERS_PROJECT}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.etcd_volume_size" \
+ "${ETCD_VOLUME_SIZE}Gi" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.openshift_release" \
+ "${OPENSHIFT_RELEASE}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.storage_class" \
+ "${STORAGE_CLASS}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.control_plane_availability" \
+ "${CONTROL_PLANE_AVAILABILITY}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.worker_count" \
+ "${WORKER_COUNT}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.worker_cores" \
+ "${WORKER_CORES}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.worker_memory" \
+ "${WORKER_MEMORY}Gi" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.worker_volume_size" \
+ "${WORKER_VOLUME_SIZE}Gi" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}\")" | \
+ patch_replace \
+ ".spec.postBuild.substitute.cluster_project" \
+ "${CLUSTER_PROJECT}" \
+ "| select(.kind == \"Kustomization\") | select(.metadata.name == \"${CLUSTER_KUSTOMIZATION_NAME}-ns\")" | \
+ rename_file_in_items \
+ "${TEMPLATE_MANIFEST_FILENAME}" \
+ "${MANIFEST_FILENAME}" | \
+ prepend_folder_path "${CLUSTER_KUSTOMIZATION_NAME}/" | \
+ list2folder_cp_over \
+ "${TARGET_FOLDER}"
+
+ echo "" | \
+ make_generator \
+ "pull-secret.yaml" \
+ kubectl_encrypt \
+ "${PUBLIC_KEY_ACM}" \
+ create \
+ secret \
+ generic \
+ "pullsecret-cluster-${CLUSTER_NAME}" \
+ --namespace="${HOSTED_CLUSTERS_PROJECT}" \
+ --from-file=".dockerconfigjson"=<(echo "${DOCKERCONFIGJSON}") \
+ -o=yaml \
+ --dry-run=client | \
+ make_generator \
+ "ssh-key-secret.yaml" \
+ kubectl_encrypt \
+ "${PUBLIC_KEY_ACM}" \
+ create \
+ secret \
+ generic \
+ "sshkey-cluster-${CLUSTER_NAME}" \
+ --namespace="${HOSTED_CLUSTERS_PROJECT}" \
+ --from-file='id_rsa.pub'=<(echo "${INFRA_PUBLIC_SSH_KEY}") \
+ -o=yaml \
+ --dry-run=client | \
+ list2folder_cp_over \
+ "${TARGET_FOLDER}/${CLUSTER_KUSTOMIZATION_NAME}"
+
+ # Bootstrap (unless asked to skip)
+ if [[ "${SKIP_BOOTSTRAP,,}" == "true" ]]; then
+ return 0
+ fi
+
+ local CLUSTER_KUBECONFIG_SECRET_NAME="${CLUSTER_KUSTOMIZATION_NAME}-admin-kubeconfig"
+ local CLUSTER_KUBECONFIG_SECRET_KEY="kubeconfig"
+ local BOOTSTRAP_KUSTOMIZATION_NAMESPACE="${HOSTED_CLUSTERS_PROJECT}"
+ local CLUSTER_KUSTOMIZATION_NAMESPACE="managed-resources"
+ local BOOTSTRAP_SECRET_NAMESPACE="managed-resources"
+
+ create_bootstrap_for_remote_cluster \
+ "${CLUSTER_NAME}" \
+ "${CLUSTER_KUSTOMIZATION_NAME}" \
+ "${FLEET_REPO_DIR}" \
+ "${SW_CATALOGS_REPO_DIR}" \
+ "${FLEET_REPO_URL}" \
+ "${SW_CATALOGS_REPO_URL}" \
+ "${MGMT_PROJECT_NAME}" \
+ "${PUBLIC_KEY_ACM}" \
+ "${PUBLIC_KEY_NEW_CLUSTER}" \
+ "${PRIVATE_KEY_NEW_CLUSTER}" \
+ "false" \
+ "${MGMT_CLUSTER_NAME}" \
+ "${CLUSTER_KUBECONFIG_SECRET_NAME}" \
+ "${CLUSTER_KUBECONFIG_SECRET_KEY}" \
+ "${SW_CATALOGS_REPO_DIR}/cloud-resources/flux-remote-bootstrap/cluster-base-openshift/templates" \
+ "${BOOTSTRAP_KUSTOMIZATION_NAMESPACE}" \
+ "${CLUSTER_KUSTOMIZATION_NAMESPACE}" \
+ "${BOOTSTRAP_SECRET_NAMESPACE}"
+
+}
+
+# Update remote Openshift cluster via ACM
+function update_openshift_cluster {
+ local CLUSTER_KUSTOMIZATION_NAME="${1}"
+ local CLUSTER_NAME="${2}"
+ # This has to be void. Stored in database
+ local K8S_VERSION="${3:-"''"}"
+ # SOPS-AGE related
+ local PUBLIC_KEY_ACM="${4}"
+ local PUBLIC_KEY_NEW_CLUSTER="${5:-"${PUBLIC_KEY_NEW_CLUSTER}"}"
+ local PRIVATE_KEY_NEW_CLUSTER="${6:-"${PRIVATE_KEY_NEW_CLUSTER}"}"
+ # OpenShift specific
+ local OPENSHIFT_RELEASE="${7}"
+ local INFRA_PUBLIC_SSH_KEY="${8}"
+ local CONTROL_PLANE_AVAILABILITY="${9}"
+ local WORKER_COUNT="${10}"
+ local WORKER_CORES="${11}"
+ local WORKER_MEMORY="${12}"
+ local WORKER_VOLUME_SIZE="${13}"
+ local STORAGE_CLASS="${14}"
+ local BASE_DOMAIN="${15}"
+ local MGMT_CLUSTER_NAME="${16}"
+ local HOSTED_CLUSTERS_PROJECT="${17:-"clusters"}"
+ local ETCD_VOLUME_SIZE="${18:-"8"}"
+ # GitOps retaled
+ local FLEET_REPO_DIR="${19:-"${FLEET_REPO_DIR}"}"
+ local FLEET_REPO_URL="${20:-"${FLEET_REPO_URL}"}"
+ local SW_CATALOGS_REPO_DIR="${21:-"${SW_CATALOGS_REPO_DIR}"}"
+ local SW_CATALOGS_REPO_URL="${22:-"${SW_CATALOGS_REPO_URL}"}"
+ local SKIP_BOOTSTRAP="${23:-"false"}"
+ # Only change if absolutely needeed
+ local MGMT_PROJECT_NAME="${24:-"osm_admin"}"
+
+ # Determine key folders in Fleet
+ local MGMT_RESOURCES_DIR="${FLEET_REPO_DIR}/${MGMT_PROJECT_NAME}/managed-resources/${MGMT_CLUSTER_NAME}"
+
+ # Updating no new cluster
+ local SKIP_BOOTSTRAP="true"
+
+ create_openshift_cluster \
+ "${CLUSTER_KUSTOMIZATION_NAME}" \
+ "${CLUSTER_NAME}" \
+ "${K8S_VERSION}" \
+ "${PUBLIC_KEY_ACM}" \
+ "${PUBLIC_KEY_NEW_CLUSTER}" \
+ "${PRIVATE_KEY_NEW_CLUSTER}" \
+ "${OPENSHIFT_RELEASE}" \
+ "${INFRA_PUBLIC_SSH_KEY}" \
+ "${CONTROL_PLANE_AVAILABILITY}" \
+ "${WORKER_COUNT}" \
+ "${WORKER_CORES}" \
+ "${WORKER_MEMORY}" \
+ "${WORKER_VOLUME_SIZE}" \
+ "${STORAGE_CLASS}" \
+ "${BASE_DOMAIN}" \
+ "${MGMT_CLUSTER_NAME}" \
+ "${HOSTED_CLUSTERS_PROJECT}" \
+ "${ETCD_VOLUME_SIZE}" \
+ "${FLEET_REPO_DIR}" \
+ "${FLEET_REPO_URL}" \
+ "${SW_CATALOGS_REPO_DIR}" \
+ "${SW_CATALOGS_REPO_URL}" \
+ "${SKIP_BOOTSTRAP}" \
+ "${MGMT_PROJECT_NAME}"
+}
# ----- Helper functions for adding/removing a profile from a cluster -----
}
+# Create a CloudConfig for CAPI provider
+function create_capi_openstack_cloudconf() {
+ local OPENSTACK_CLOUD_NAME="${1}"
+ local PUBLIC_KEY="${2:-"${PUBLIC_KEY_MGMT}"}"
+ local CONFIG_DIR="${3:-"${MGMT_ADDON_CONFIG_DIR}"}"
+
+ local NAMESPACE="managed-resources"
+
+ local CLOUDS_YAML="${OPENSTACK_CLOUDS_YAML}"
+ local CACERT="${OPENSTACK_CACERT}"
+
+ local CLOUD_CREDENTIALS_SECRET_NAME="${OPENSTACK_CLOUD_NAME}-capo-config"
+ local CLOUD_CREDENTIALS_CLOUDS_KEY="clouds.yaml"
+ local CLOUD_CREDENTIALS_CACERT_KEY="cacert"
+ local CLOUD_CREDENTIALS_FILENAME="credentials-secret.yaml"
+
+ local CLOUD_CREDENTIALS_TOML_SECRET_NAME="${OPENSTACK_CLOUD_NAME}-capo-config-toml"
+ local CLOUD_CREDENTIALS_TOML_FILENAME="credentials-toml-secret.yaml"
+
+ local TARGET_FOLDER="${CONFIG_DIR}/capi-providerconfigs/capo/${OPENSTACK_CLOUD_NAME}-config"
+ mkdir -p "${TARGET_FOLDER}"
+
+ echo "" | \
+ make_generator \
+ "${CLOUD_CREDENTIALS_FILENAME}" \
+ kubectl_encrypt \
+ "${PUBLIC_KEY}" \
+ create \
+ secret \
+ generic \
+ "${CLOUD_CREDENTIALS_SECRET_NAME}" \
+ --namespace="${NAMESPACE}" \
+ --from-file="${CLOUD_CREDENTIALS_CLOUDS_KEY}"=<(echo "${CLOUDS_YAML}") \
+ --from-file="${CLOUD_CREDENTIALS_CACERT_KEY}"=<(echo "${CACERT}") \
+ -o=yaml \
+ --dry-run=client | \
+ make_generator \
+ "${CLOUD_CREDENTIALS_TOML_FILENAME}" \
+ kubectl_encrypt \
+ "${PUBLIC_KEY}" \
+ create \
+ secret \
+ generic \
+ "${CLOUD_CREDENTIALS_TOML_SECRET_NAME}" \
+ --namespace="${NAMESPACE}" \
+ --from-file="os_auth_url"=<(echo "${OS_AUTH_URL}") \
+ --from-file="os_region_name"=<(echo "${OS_REGION_NAME}") \
+ --from-file="os_username"=<(echo "${OS_USERNAME}") \
+ --from-file="os_password"=<(echo "${OS_PASSWORD}") \
+ --from-file="os_project_id"=<(echo "${OS_PROJECT_ID}") \
+ --from-file="os_project_domain_id"=<(echo "${OS_PROJECT_DOMAIN_ID}") \
+ -o=yaml \
+ --dry-run=client | \
+ list2folder_cp_over \
+ "${TARGET_FOLDER}"
+}
+
+# Update a CloudConfig for CAPI provider
+function update_capi_openstack_cloudconf() {
+ local CLOUD_CONFIG_NAME="${1}"
+ local PUBLIC_KEY="${2:-"${PUBLIC_KEY_MGMT}"}"
+ local CONFIG_DIR="${3:-"${MGMT_ADDON_CONFIG_DIR}"}"
+
+ delete_capi_openstack_cloudconf \
+ "${CLOUD_CONFIG_NAME}" \
+ "${CONFIG_DIR}"
+
+ create_capi_openstack_cloudconf \
+ "${CLOUD_CONFIG_NAME}" \
+ "${PUBLIC_KEY}" \
+ "${CONFIG_DIR}"
+}
+
+
+# Delete a CloudConfig for CAPI provider
+function delete_capi_openstack_cloudconf() {
+ local OPENSTACK_CLOUD_NAME="$1"
+ local CONFIG_DIR="${2:-"${MGMT_ADDON_CONFIG_DIR}"}"
+
+ local TARGET_FOLDER="${CONFIG_DIR}/capi-providerconfigs/capo/${OPENSTACK_CLOUD_NAME}-config"
+
+ # Delete the encrypted secrets files.
+ rm -rf "${TARGET_FOLDER}"
+}
+
# Helper function to return the relative path of a location in SW Catalogs for an OKA
function path_to_catalog() {
local OKA_TYPE="$1"
export KUBECONFIG_MGMT_CLUSTER=
export KUBECONFIG_OSM_CLUSTER=
export OSM_BEHIND_PROXY=
+export OPENSHIFT_MGMT_CLUSTER=
+export MGMT_CLUSTER_CA_FILE=
+export OSM_K8S_NGINX_IPADDRESS=
\ No newline at end of file
export KUBECONFIG_MGMT_CLUSTER=${KUBECONFIG_MGMT_CLUSTER}
export KUBECONFIG_OSM_CLUSTER=${KUBECONFIG_OSM_CLUSTER}
export OSM_BEHIND_PROXY=${OSM_BEHIND_PROXY}
+export OPENSHIFT_MGMT_CLUSTER=${OPENSHIFT_MGMT_CLUSTER}
+export MGMT_CLUSTER_CA_FILE=${MGMT_CLUSTER_CA_FILE}
+export OSM_K8S_NGINX_IPADDRESS=${OSM_K8S_NGINX_IPADDRESS}
EOF
cat "${OSM_HOME_DIR}/user-install-options.rc"
source "${CREDENTIALS_DIR}/git_environment.rc"
OSM_HELM_WORK_DIR="/etc/osm/helm"
-OSM_K8S_EXTERNAL_IP=${OSM_K8S_EXTERNAL_IP:-""}
KUBECONFIG_AUX_CLUSTER_FILE="${OSM_HOME_DIR}/clusters/kubeconfig-aux-svc.yaml"
KUBECONFIG_MGMT_CLUSTER_FILE="${OSM_HOME_DIR}/clusters/kubeconfig-mgmt.yaml"
[ "${HERE}" == "/usr/share/osm-devops/installers" ] || OSM_HELM_UPDATE_DEPENDENCIES="y"
fi
export KUBECONFIG="${OSM_HOME_DIR}/clusters/kubeconfig-osm.yaml"
+if [ -z "${OSM_K8S_NGINX_IPADDRESS}" ]; then
+ echo "OSM_K8S_NGINX_IPADDRESS is not set, will try to get it from the cluster"
+ OSM_K8S_NGINX_IPADDRESS=$(kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2>/dev/null)
+fi
+echo "Using OSM_K8S_NGINX_IPADDRESS=${OSM_K8S_NGINX_IPADDRESS}"
# Create folder to store helm values
sudo mkdir -p ${OSM_HELM_WORK_DIR}
# Saving secrets
echo "Creating namespace ${OSM_NAMESPACE}"
-kubectl create ns ${OSM_NAMESPACE}
+kubectl get ns "${OSM_NAMESPACE}" >/dev/null 2>&1 || kubectl create ns "${OSM_NAMESPACE}"
echo "Saving age keys in OSM cluster"
+kubectl -n ${OSM_NAMESPACE} get secret mgmt-cluster-age-keys >/dev/null 2>&1 || \
kubectl -n ${OSM_NAMESPACE} create secret generic mgmt-cluster-age-keys --from-file=privkey="${CREDENTIALS_DIR}/age.mgmt.key" --from-file=pubkey="${CREDENTIALS_DIR}/age.mgmt.pub"
echo "Creating secrets with kubeconfig files"
-kubectl -n ${OSM_NAMESPACE} create secret generic auxcluster-secret --from-file=kubeconfig="${KUBECONFIG_AUX_CLUSTER_FILE}"
-kubectl -n ${OSM_NAMESPACE} create secret generic mgmtcluster-secret --from-file=kubeconfig="${KUBECONFIG_MGMT_CLUSTER_FILE}"
-
+if [ -f "${KUBECONFIG_AUX_CLUSTER_FILE}" ]; then
+ kubectl -n ${OSM_NAMESPACE} get secret auxcluster-secret >/dev/null 2>&1 || \
+ kubectl -n ${OSM_NAMESPACE} create secret generic auxcluster-secret --from-file=kubeconfig="${KUBECONFIG_AUX_CLUSTER_FILE}"
+fi
+if [ -f "${KUBECONFIG_MGMT_CLUSTER_FILE}" ]; then
+ kubectl -n ${OSM_NAMESPACE} get secret mgmtcluster-secret >/dev/null 2>&1 || \
+ kubectl -n ${OSM_NAMESPACE} create secret generic mgmtcluster-secret --from-file=kubeconfig="${KUBECONFIG_MGMT_CLUSTER_FILE}"
+fi
# Update helm dependencies
[ -n "${OSM_HELM_UPDATE_DEPENDENCIES}" ] && \
echo "Updating helm dependencies" && \
[ ! "$OSM_DOCKER_TAG" == "testing-daily" ] && OSM_HELM_OPTS="${OSM_HELM_OPTS} --set-string global.image.tag=${OSM_DOCKER_TAG}"
[ ! "$OSM_DOCKER_TAG" == "testing-daily" ] && OSM_HELM_OPTS="${OSM_HELM_OPTS} --set prometheus.server.sidecarContainers.prometheus-config-sidecar.image=${DOCKER_REGISTRY_URL}${DOCKER_USER}/prometheus:${OSM_DOCKER_TAG}"
-OSM_HELM_OPTS="${OSM_HELM_OPTS} --set global.hostname=${OSM_K8S_EXTERNAL_IP}.nip.io"
-OSM_HELM_OPTS="${OSM_HELM_OPTS} --set grafana.ingress.hosts={grafana.${OSM_K8S_EXTERNAL_IP}.nip.io}"
-OSM_HELM_OPTS="${OSM_HELM_OPTS} --set prometheus.server.ingress.hosts={prometheus.${OSM_K8S_EXTERNAL_IP}.nip.io}"
-# OSM_HELM_OPTS="${OSM_HELM_OPTS} --set prometheus.alertmanager.ingress.hosts={alertmanager.${OSM_K8S_EXTERNAL_IP}.nip.io}"
+OSM_BASE_DOMAIN="${OSM_BASE_DOMAIN:-"${OSM_K8S_NGINX_IPADDRESS}.nip.io"}"
+OSM_HELM_OPTS="${OSM_HELM_OPTS} --set global.hostname=${OSM_BASE_DOMAIN}"
+OSM_HELM_OPTS="${OSM_HELM_OPTS} --set grafana.ingress.hosts={grafana.${OSM_BASE_DOMAIN}}"
+OSM_HELM_OPTS="${OSM_HELM_OPTS} --set prometheus.server.ingress.hosts={prometheus.${OSM_BASE_DOMAIN}}"
+# OSM_HELM_OPTS="${OSM_HELM_OPTS} --set prometheus.alertmanager.ingress.hosts={alertmanager.${OSM_BASE_DOMAIN}}"
if [ -z "${OSM_GITOPS_ENABLED}" ]; then
OSM_HELM_OPTS="${OSM_HELM_OPTS} --set global.gitops.enabled=false"
else
echo -e "Saving OSM enviroment to credentials folder..."
OSM_HOSTNAME=$(kubectl get --namespace osm -o jsonpath="{.spec.rules[0].host}" ingress nbi-ingress)
-# OSM_HOSTNAME="nbi.${OSM_K8S_EXTERNAL_IP}.nip.io:443"
+# OSM_HOSTNAME="nbi.${OSM_BASE_DOMAIN}:443"
echo -e "OSM HOSTNAME: ${OSM_HOSTNAME}"
cat << EOF > "${CREDENTIALS_DIR}/osm_environment.rc"
# Secrets to access both Git repos
# (NOTE: these are the last secrets to be added imperatively)
kubectl delete secret fleet-repo --namespace flux-system 2> /dev/null || true
-kubectl create secret generic fleet-repo \
- --namespace flux-system \
- --from-literal=username="${FLEET_REPO_GIT_USERNAME}" \
- --from-literal=password="${FLEET_REPO_GIT_USER_PASS}"
-
+if [ -n "${MGMT_CLUSTER_CA_FILE}" ]; then
+ kubectl create secret generic fleet-repo \
+ --namespace flux-system \
+ --from-literal=username="${FLEET_REPO_GIT_USERNAME}" \
+ --from-literal=password="${FLEET_REPO_GIT_USER_PASS}" \
+ --from-file=ca.crt="${MGMT_CLUSTER_CA_FILE}"
+else
+ kubectl create secret generic fleet-repo \
+ --namespace flux-system \
+ --from-literal=username="${FLEET_REPO_GIT_USERNAME}" \
+ --from-literal=password="${FLEET_REPO_GIT_USER_PASS}"
+fi
kubectl delete secret sw-catalogs --namespace flux-system 2> /dev/null || true
-kubectl create secret generic sw-catalogs \
- --namespace flux-system \
- --from-literal=username="${SW_CATALOGS_REPO_GIT_USERNAME}" \
- --from-literal=password="${SW_CATALOGS_REPO_GIT_USER_PASS}"
-
+if [ -n "${MGMT_CLUSTER_CA_FILE}" ]; then
+ kubectl create secret generic sw-catalogs \
+ --namespace flux-system \
+ --from-literal=username="${SW_CATALOGS_REPO_GIT_USERNAME}" \
+ --from-literal=password="${SW_CATALOGS_REPO_GIT_USER_PASS}" \
+ --from-file=ca.crt="${MGMT_CLUSTER_CA_FILE}"
+else
+ kubectl create secret generic sw-catalogs \
+ --namespace flux-system \
+ --from-literal=username="${SW_CATALOGS_REPO_GIT_USERNAME}" \
+ --from-literal=password="${SW_CATALOGS_REPO_GIT_USER_PASS}"
+fi
# Render Flux `Kustomizations` to sync with default profiles
envsubst < "${TEMPLATES_DIR}/infra-controllers.yaml" > "${CLUSTER_DIR}/infra-controllers.yaml"
envsubst < "${TEMPLATES_DIR}/infra-configs.yaml" > "${CLUSTER_DIR}/infra-configs.yaml"
source "${HERE}/library/trap.sh"
+# Preparation for Openshift
+if [ -n "${OPENSHIFT_MGMT_CLUSTER}" ]; then
+ m "Detected OpenShift management cluster, initilializing flux with SCC..." "${GREEN}"
+ # Preparation for Openshift
+ pushd "${FLEET_REPO_DIR}" > /dev/null
+ FLUX_SYSTEM_DIR="clusters/_management/flux-system"
+ FLUX_SYSTEM_SW_CATALOG_DIR="${HERE}/../templates/sw-catalogs/cloud-resources/flux-remote-bootstrap/cluster-base-openshift/templates/flux-system"
+ mkdir -p "${FLUX_SYSTEM_DIR}"
+ touch "${FLUX_SYSTEM_DIR}/gotk-components.yaml"
+ touch "${FLUX_SYSTEM_DIR}/gotk-sync.yaml"
+ cp "${FLUX_SYSTEM_SW_CATALOG_DIR}/scc.yaml" "${FLUX_SYSTEM_DIR}"
+ cp "${FLUX_SYSTEM_SW_CATALOG_DIR}/kustomization.yaml" "${FLUX_SYSTEM_DIR}"
+ # git status
+ git add -A
+ git commit -m "init flux"
+ git pull origin main
+ git push -u origin main
+ popd > /dev/null
+fi
+
# Bootstrap
GIT_PATH=./clusters/_management
GIT_BRANCH=main
-flux bootstrap git \
- --url=${FLEET_REPO_HTTP_URL} \
- --allow-insecure-http=true \
- --username=${FLEET_REPO_GIT_USERNAME} \
- --password="${FLEET_REPO_GIT_USER_PASS}" \
- --token-auth=true \
- --branch=${GIT_BRANCH} \
- --path=${GIT_PATH}
+if [ -n "${MGMT_CLUSTER_CA_FILE}" ]; then
+ flux bootstrap git \
+ --url=${FLEET_REPO_HTTP_URL} \
+ --allow-insecure-http=true \
+ --username=${FLEET_REPO_GIT_USERNAME} \
+ --password="${FLEET_REPO_GIT_USER_PASS}" \
+ --token-auth=true \
+ --branch=${GIT_BRANCH} \
+ --ca-file=${MGMT_CLUSTER_CA_FILE} \
+ --path=${GIT_PATH}
+else
+ flux bootstrap git \
+ --url=${FLEET_REPO_HTTP_URL} \
+ --allow-insecure-http=true \
+ --username=${FLEET_REPO_GIT_USERNAME} \
+ --password="${FLEET_REPO_GIT_USER_PASS}" \
+ --token-auth=true \
+ --branch=${GIT_BRANCH} \
+ --path=${GIT_PATH}
+fi
# Check if successful
flux check
kind: Kustomization
metadata:
name: ${CLUSTER_KUSTOMIZATION_NAME}-bstrp-ns
- namespace: managed-resources
+ namespace: ${BOOTSTRAP_KUSTOMIZATION_NAMESPACE}
labels:
cluster: ${CLUSTER_KUSTOMIZATION_NAME}
spec:
timeout: 5m
dependsOn:
- name: ${CLUSTER_KUSTOMIZATION_NAME}
+ namespace: ${CLUSTER_KUSTOMIZATION_NAMESPACE}
prune: true
# wait: true
# force: true
path: ./cloud-resources/flux-remote-bootstrap/bootstrap/manifests/namespaces
kubeConfig:
secretRef:
- name: kubeconfig-${CLUSTER_KUSTOMIZATION_NAME}
- key: kubeconfig
+ name: ${CLUSTER_KUBECONFIG_SECRET_NAME}
+ key: ${CLUSTER_KUBECONFIG_SECRET_KEY}
---
# Creates remote `flux-system.flux-system` secret
kind: Kustomization
metadata:
name: ${CLUSTER_KUSTOMIZATION_NAME}-bstrp-secret-flux
- namespace: managed-resources
+ namespace: ${BOOTSTRAP_KUSTOMIZATION_NAMESPACE}
labels:
cluster: ${CLUSTER_KUSTOMIZATION_NAME}
spec:
path: ./cloud-resources/flux-remote-bootstrap/bootstrap/manifests/secret
kubeConfig:
secretRef:
- name: kubeconfig-${CLUSTER_KUSTOMIZATION_NAME}
- key: kubeconfig
+ name: ${CLUSTER_KUBECONFIG_SECRET_NAME}
+ key: ${CLUSTER_KUBECONFIG_SECRET_KEY}
patches:
- patch: |-
apiVersion: v1
- kind: Secret
name: flux-system
+---
+# Creates remote `flux-system.managed-resources` secret
+apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
+kind: Kustomization
+metadata:
+ name: ${CLUSTER_KUSTOMIZATION_NAME}-bstrp-secret-managedresources-flux
+ namespace: ${BOOTSTRAP_KUSTOMIZATION_NAMESPACE}
+ labels:
+ cluster: ${CLUSTER_KUSTOMIZATION_NAME}
+spec:
+ # interval: 1h
+ interval: 5m
+ retryInterval: 1m
+ timeout: 5m
+ dependsOn:
+ - name: ${CLUSTER_KUSTOMIZATION_NAME}-bstrp-ns
+ prune: true
+ # wait: true
+ force: true
+ sourceRef:
+ kind: GitRepository
+ name: sw-catalogs
+ namespace: flux-system
+ path: ./cloud-resources/flux-remote-bootstrap/bootstrap/manifests/secret
+ kubeConfig:
+ secretRef:
+ name: ${CLUSTER_KUBECONFIG_SECRET_NAME}
+ key: ${CLUSTER_KUBECONFIG_SECRET_KEY}
+ patches:
+ - patch: |-
+ apiVersion: v1
+ kind: Secret
+ metadata:
+ name: ${secret_name}
+ namespace: ${secret_namespace}
+ stringData:
+ username: ${username}
+ password: ${password}
+ # Inputs:
+ postBuild:
+ substitute:
+ secret_name: flux-system
+ secret_namespace: ${BOOTSTRAP_SECRET_NAMESPACE}
+ substituteFrom:
+ - kind: Secret
+ name: flux-system
+
---
# Creates remote `sops-age` secret
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: ${CLUSTER_KUSTOMIZATION_NAME}-bstrp-secret-sops
- namespace: managed-resources
+ namespace: ${BOOTSTRAP_KUSTOMIZATION_NAMESPACE}
labels:
cluster: ${CLUSTER_KUSTOMIZATION_NAME}
spec:
path: ./cloud-resources/flux-remote-bootstrap/bootstrap/manifests/secret
kubeConfig:
secretRef:
- name: kubeconfig-${CLUSTER_KUSTOMIZATION_NAME}
- key: kubeconfig
+ name: ${CLUSTER_KUBECONFIG_SECRET_NAME}
+ key: ${CLUSTER_KUBECONFIG_SECRET_KEY}
patches:
- patch: |-
apiVersion: v1
kind: Kustomization
metadata:
name: ${CLUSTER_KUSTOMIZATION_NAME}-bstrp-secret-fleet
- namespace: managed-resources
+ namespace: ${BOOTSTRAP_KUSTOMIZATION_NAMESPACE}
labels:
cluster: ${CLUSTER_KUSTOMIZATION_NAME}
spec:
path: ./cloud-resources/flux-remote-bootstrap/bootstrap/manifests/secret
kubeConfig:
secretRef:
- name: kubeconfig-${CLUSTER_KUSTOMIZATION_NAME}
- key: kubeconfig
+ name: ${CLUSTER_KUBECONFIG_SECRET_NAME}
+ key: ${CLUSTER_KUBECONFIG_SECRET_KEY}
patches:
- patch: |-
apiVersion: v1
- kind: Secret
name: fleet-repo
+---
+# Creates remote `fleet-repo.managed-resources` secret
+apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
+kind: Kustomization
+metadata:
+ name: ${CLUSTER_KUSTOMIZATION_NAME}-bstrp-secret-managedresources-fleet
+ namespace: ${BOOTSTRAP_KUSTOMIZATION_NAMESPACE}
+ labels:
+ cluster: ${CLUSTER_KUSTOMIZATION_NAME}
+spec:
+ # interval: 1h
+ interval: 5m
+ retryInterval: 1m
+ timeout: 5m
+ dependsOn:
+ - name: ${CLUSTER_KUSTOMIZATION_NAME}-bstrp-ns
+ prune: true
+ # wait: true
+ force: true
+ sourceRef:
+ kind: GitRepository
+ name: sw-catalogs
+ namespace: flux-system
+ path: ./cloud-resources/flux-remote-bootstrap/bootstrap/manifests/secret
+ kubeConfig:
+ secretRef:
+ name: ${CLUSTER_KUBECONFIG_SECRET_NAME}
+ key: ${CLUSTER_KUBECONFIG_SECRET_KEY}
+ patches:
+ - patch: |-
+ apiVersion: v1
+ kind: Secret
+ metadata:
+ name: ${secret_name}
+ namespace: ${secret_namespace}
+ stringData:
+ username: ${username}
+ password: ${password}
+ # Inputs:
+ postBuild:
+ substitute:
+ secret_name: fleet-repo
+ secret_namespace: ${BOOTSTRAP_SECRET_NAMESPACE}
+ substituteFrom:
+ - kind: Secret
+ name: fleet-repo
+
---
# Creates remote `sw-catalogs.flux-system` secret
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: ${CLUSTER_KUSTOMIZATION_NAME}-bstrp-secret-catalogs
- namespace: managed-resources
+ namespace: ${BOOTSTRAP_KUSTOMIZATION_NAMESPACE}
labels:
cluster: ${CLUSTER_KUSTOMIZATION_NAME}
spec:
path: ./cloud-resources/flux-remote-bootstrap/bootstrap/manifests/secret
kubeConfig:
secretRef:
- name: kubeconfig-${CLUSTER_KUSTOMIZATION_NAME}
- key: kubeconfig
+ name: ${CLUSTER_KUBECONFIG_SECRET_NAME}
+ key: ${CLUSTER_KUBECONFIG_SECRET_KEY}
patches:
- patch: |-
apiVersion: v1
- kind: Secret
name: sw-catalogs
+---
+# Creates remote `sw-catalogs.managed-resources` secret
+apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
+kind: Kustomization
+metadata:
+ name: ${CLUSTER_KUSTOMIZATION_NAME}-bstrp-secret-managedresources-catalogs
+ namespace: ${BOOTSTRAP_KUSTOMIZATION_NAMESPACE}
+ labels:
+ cluster: ${CLUSTER_KUSTOMIZATION_NAME}
+spec:
+ # interval: 1h
+ interval: 5m
+ retryInterval: 1m
+ timeout: 5m
+ dependsOn:
+ - name: ${CLUSTER_KUSTOMIZATION_NAME}-bstrp-ns
+ prune: true
+ # wait: true
+ force: true
+ sourceRef:
+ kind: GitRepository
+ name: sw-catalogs
+ namespace: flux-system
+ path: ./cloud-resources/flux-remote-bootstrap/bootstrap/manifests/secret
+ kubeConfig:
+ secretRef:
+ name: ${CLUSTER_KUBECONFIG_SECRET_NAME}
+ key: ${CLUSTER_KUBECONFIG_SECRET_KEY}
+ patches:
+ - patch: |-
+ apiVersion: v1
+ kind: Secret
+ metadata:
+ name: ${secret_name}
+ namespace: ${secret_namespace}
+ stringData:
+ username: ${username}
+ password: ${password}
+ # Inputs:
+ postBuild:
+ substitute:
+ secret_name: sw-catalogs
+ secret_namespace: ${BOOTSTRAP_SECRET_NAMESPACE}
+ substituteFrom:
+ - kind: Secret
+ name: sw-catalogs
+
---
# Remote installation of Flux controller (to let the cluster be autonomous)
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: ${CLUSTER_KUSTOMIZATION_NAME}-bstrp-fluxctrl
- namespace: managed-resources
+ namespace: ${BOOTSTRAP_KUSTOMIZATION_NAMESPACE}
labels:
cluster: ${CLUSTER_KUSTOMIZATION_NAME}
spec:
namespace: flux-system
kubeConfig:
secretRef:
- name: kubeconfig-${CLUSTER_KUSTOMIZATION_NAME}
- key: kubeconfig
+ name: ${CLUSTER_KUBECONFIG_SECRET_NAME}
+ key: ${CLUSTER_KUBECONFIG_SECRET_KEY}
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+---
+apiVersion: kustomize.toolkit.fluxcd.io/v1
+kind: Kustomization
+metadata:
+ name: apps
+ namespace: flux-system
+ labels:
+ osm_profile_type: apps
+spec:
+ interval: 10m0s
+ dependsOn:
+ - name: infra-configs
+ sourceRef:
+ kind: GitRepository
+ name: fleet-repo
+ path: ${APPS_PATH}
+ prune: true
+ wait: true
+ timeout: 5m0s
+ # Decryption configuration starts here
+ decryption:
+ provider: sops
+ secretRef:
+ name: sops-age
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: GitRepository
+metadata:
+ name: fleet-repo
+ namespace: flux-system
+spec:
+ interval: 1m0s
+ ref:
+ branch: main
+ secretRef:
+ name: fleet-repo
+ url: ${FLEET_REPO_URL}
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+# This manifest was generated by flux. DO NOT EDIT.
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: GitRepository
+metadata:
+ name: flux-system
+ namespace: flux-system
+spec:
+ interval: 1m0s
+ ref:
+ branch: main
+ secretRef:
+ name: flux-system
+ url: ${FLEET_REPO_URL}
+---
+apiVersion: kustomize.toolkit.fluxcd.io/v1
+kind: Kustomization
+metadata:
+ name: flux-system
+ namespace: flux-system
+spec:
+ interval: 10m0s
+ path: ./clusters/${CLUSTER_KUSTOMIZATION_NAME}
+ prune: true
+ sourceRef:
+ kind: GitRepository
+ name: flux-system
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+ - gotk-components.yaml
+ - gotk-sync.yaml
+ - scc.yaml
+patches:
+ - patch: |
+ apiVersion: apps/v1
+ kind: Deployment
+ metadata:
+ name: all
+ spec:
+ template:
+ spec:
+ securityContext:
+ $patch: delete
+ containers:
+ - name: manager
+ securityContext:
+ runAsUser: 65534
+ seccompProfile:
+ $patch: delete
+ target:
+ kind: Deployment
+ labelSelector: app.kubernetes.io/part-of=flux
+ - patch: |-
+ - op: remove
+ path: /metadata/labels/pod-security.kubernetes.io~1warn
+ - op: remove
+ path: /metadata/labels/pod-security.kubernetes.io~1warn-version
+ target:
+ kind: Namespace
+ labelSelector: app.kubernetes.io/part-of=flux
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+# Allow Flux controllers to run as non-root on OpenShift
+# Docs: https://fluxcd.io/flux/installation/configuration/openshift/
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: flux-scc
+rules:
+ - apiGroups:
+ - security.openshift.io
+ resources:
+ - securitycontextconstraints
+ resourceNames:
+ - nonroot
+ verbs:
+ - use
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: flux-scc
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: flux-scc
+subjects:
+ - kind: ServiceAccount
+ name: source-controller
+ namespace: flux-system
+ - kind: ServiceAccount
+ name: kustomize-controller
+ namespace: flux-system
+ - kind: ServiceAccount
+ name: helm-controller
+ namespace: flux-system
+ - kind: ServiceAccount
+ name: notification-controller
+ namespace: flux-system
+ - kind: ServiceAccount
+ name: image-reflector-controller
+ namespace: flux-system
+ - kind: ServiceAccount
+ name: image-automation-controller
+ namespace: flux-system
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+---
+apiVersion: kustomize.toolkit.fluxcd.io/v1
+kind: Kustomization
+metadata:
+ name: infra-configs
+ namespace: flux-system
+ labels:
+ osm_profile_type: infra-configs
+spec:
+ dependsOn:
+ - name: infra-controllers
+ interval: 1h
+ retryInterval: 1m
+ timeout: 5m
+ sourceRef:
+ kind: GitRepository
+ name: fleet-repo
+ path: ${INFRA_CONFIGS_PATH}
+ prune: true
+ # Decryption configuration starts here
+ decryption:
+ provider: sops
+ secretRef:
+ name: sops-age
+ # patches:
+ # - patch: |
+ # - op: replace
+ # path: /spec/acme/server
+ # value: https://acme-v02.api.letsencrypt.org/directory
+ # target:
+ # kind: ClusterIssuer
+ # name: letsencrypt
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+---
+apiVersion: kustomize.toolkit.fluxcd.io/v1
+kind: Kustomization
+metadata:
+ name: infra-controllers
+ namespace: flux-system
+ labels:
+ osm_profile_type: infra-controllers
+spec:
+ interval: 1h
+ retryInterval: 1m
+ timeout: 5m
+ sourceRef:
+ kind: GitRepository
+ name: fleet-repo
+ path: ${INFRA_CONTROLLERS_PATH}
+ prune: true
+ wait: true
+ # Decryption configuration starts here
+ decryption:
+ provider: sops
+ secretRef:
+ name: sops-age
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+ # Repos
+ - fleet-repo.yaml
+ - sw-catalogs-repo.yaml
+
+ # Base cluster structure (CRDs, operators and their configs)
+ - infra-controllers.yaml
+ - infra-configs.yaml
+
+ # Managed resources
+ - managed-resources.yaml
+
+ # Managed apps
+ - apps.yaml
+
+ # Adds also the `flux-system` folder to preserve bootstrap structure
+ - flux-system
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+---
+# Namespace
+# apiVersion: v1
+# kind: Namespace
+# metadata:
+# name: managed-resources
+
+---
+# Managed resources
+apiVersion: kustomize.toolkit.fluxcd.io/v1
+kind: Kustomization
+metadata:
+ name: managed-resources
+ namespace: flux-system
+ labels:
+ osm_profile_type: managed-resources
+spec:
+ # interval: 10m0s
+ interval: 7m0s
+ dependsOn:
+ - name: infra-configs
+ sourceRef:
+ kind: GitRepository
+ name: fleet-repo
+ path: ${MANAGED_RESOURCES_PATH}
+ prune: true
+ wait: true
+ # timeout: 5m0s
+ timeout: 7m0s
+ retryInterval: 2m0s
+ # Decryption configuration starts here
+ decryption:
+ provider: sops
+ secretRef:
+ name: sops-age
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: GitRepository
+metadata:
+ name: sw-catalogs
+ namespace: flux-system
+spec:
+ interval: 1m0s
+ ref:
+ branch: main
+ secretRef:
+ name: sw-catalogs
+ url: ${SW_CATALOGS_REPO_URL}
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+apiVersion: hypershift.openshift.io/v1beta1
+kind: HostedCluster
+metadata:
+ name: ${cluster_name}
+ namespace: ${hosted_cluster_project}
+ labels:
+ cluster: ${cluster_name}
+ "cluster.open-cluster-management.io/clusterset": "default"
+spec:
+ etcd:
+ managed:
+ storage:
+ persistentVolume:
+ size: "${etcd_volume_size}"
+ storageClassName: ${storage_class}
+ type: PersistentVolume
+ managementType: Managed
+ release:
+ image: "quay.io/openshift-release-dev/ocp-release:${openshift_release}"
+ pullSecret:
+ name: "pullsecret-cluster-${cluster_name}"
+ sshKey:
+ name: "sshkey-cluster-${cluster_name}"
+ networking:
+ clusterNetwork:
+ - cidr: 10.132.0.0/14
+ serviceNetwork:
+ - cidr: 172.31.0.0/16
+ networkType: OVNKubernetes
+ controllerAvailabilityPolicy: ${control_plane_availability}
+ infrastructureAvailabilityPolicy: ${control_plane_availability}
+ platform:
+ type: KubeVirt
+ kubevirt:
+ baseDomainPassthrough: true
+ infraID: ${cluster_name}
+ services:
+ - service: OAuthServer
+ servicePublishingStrategy:
+ type: Route
+ - service: OIDC
+ servicePublishingStrategy:
+ type: Route
+ - service: Konnectivity
+ servicePublishingStrategy:
+ type: Route
+ - service: Ignition
+ servicePublishingStrategy:
+ type: Route
+ - service: APIServer
+ servicePublishingStrategy:
+ type: LoadBalancer
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+apiVersion: agent.open-cluster-management.io/v1
+kind: KlusterletAddonConfig
+metadata:
+ name: ${cluster_name}
+ namespace: ${cluster_project}
+ labels:
+ cluster: ${cluster_name}
+spec:
+ clusterName: ${cluster_name}
+ clusterNamespace: ${cluster_project}
+ clusterLabels:
+ cloud: BareMetal
+ vendor: OpenShift
+ applicationManager:
+ enabled: true
+ policyController:
+ enabled: true
+ searchCollector:
+ enabled: true
+ certPolicyController:
+ enabled: true
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+apiVersion: cluster.open-cluster-management.io/v1
+kind: ManagedCluster
+metadata:
+ annotations:
+ import.open-cluster-management.io/hosting-cluster-name: local-cluster
+ import.open-cluster-management.io/klusterlet-deploy-mode: Hosted
+ open-cluster-management/created-via: hypershift
+ labels:
+ cloud: BareMetal
+ cluster: ${cluster_name}
+ vendor: OpenShift
+ name: ${cluster_name}
+ cluster.open-cluster-management.io/clusterset: "default"
+ name: ${cluster_name}
+spec:
+ hubAcceptsClient: true
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+apiVersion: hypershift.openshift.io/v1beta1
+kind: NodePool
+metadata:
+ name: "${cluster_name}-np1"
+ namespace: ${hosted_cluster_project}
+ labels:
+ cluster: ${cluster_name}
+spec:
+ arch: amd64
+ clusterName: ${cluster_name}
+ replicas: ${worker_count}
+ management:
+ autoRepair: false
+ upgradeType: Replace
+ platform:
+ type: KubeVirt
+ kubevirt:
+ compute:
+ cores: ${worker_cores}
+ memory: "${worker_memory}"
+ rootVolume:
+ type: Persistent
+ persistent:
+ size: "${worker_volume_size}"
+ accessModes:
+ - ReadWriteMany
+ storageClass: ${storage_class}
+ volumeMode: Block
+ # defaultPodNetwork: true
+ release:
+ image: "quay.io/openshift-release-dev/ocp-release:${openshift_release}"
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: "${cluster_project}"
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: "clusters-${cluster_project}"
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: "klusterlet-${cluster_project}"
--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+---
+# TEMPLATE_PARAMETERS:
+# ===================
+#
+# CLUSTER_KUSTOMIZATION_NAME: Name of the cluster in the ACM management cluster (e.g., for `Kustomization`s).
+# CLUSTER_PROJECT: Name of one of the three projects for the cluster that will be created in the ACM management cluster.
+#
+# PARAMETERS TO PATCH:
+# ===================
+#
+# .spec.postBuild.substitute.cluster_project: Project name to be created
+
+# Cluster projects
+apiVersion: kustomize.toolkit.fluxcd.io/v1
+kind: Kustomization
+metadata:
+ name: ${CLUSTER_KUSTOMIZATION_NAME}-ns
+ namespace: managed-resources
+ labels:
+ cluster: ${CLUSTER_KUSTOMIZATION_NAME}
+spec:
+ commonMetadata:
+ labels:
+ cluster: ${CLUSTER_KUSTOMIZATION_NAME}
+ interval: 1h
+ retryInterval: 1m
+ timeout: 5m
+ sourceRef:
+ kind: GitRepository
+ name: sw-catalogs
+ namespace: flux-system
+ path: ./cloud-resources/openshift/manifests/namespaces
+ prune: true
+ # force: true
+ wait: true
+ # Input parameters
+ postBuild:
+ substitute:
+ cluster_project: ${CLUSTER_PROJECT}
+---
+# TEMPLATE_PARAMETERS:
+# ===================
+#
+# CLUSTER_KUSTOMIZATION_NAME: Name of the cluster in the management cluster (e.g., for `Kustomization`s).
+# - Alternatively, it can be patched at:
+# .metadata.name
+# .metadata.labels.cluster
+# .spec.commonMetadata.labels.cluster
+# .spec.postBuild.substitute.cluster_resource_name
+#
+# PARAMETERS TO PATCH:
+# ===================
+#
+# .spec.postBuild.substitute.base_domain: Domain name to use as base.
+# .spec.postBuild.substitute.cluster_name: Name of the cluster in the target cloud. It may differ from `CLUSTER_KUSTOMIZATION_NAME` since naming restrictions are often different from K8s resource naming restrictions (e.g., hyphens vs. underscores).
+# .spec.postBuild.substitute.cluster_project: Project name to use
+# .spec.postBuild.substitute.hosted_cluster_project: Common project name to use for use with all workload clusters.
+# .spec.postBuild.substitute.etcd_volume_size: Volume size of ETCD in Gi
+# .spec.postBuild.substitute.openshift_release: Flavor of worker node VMs.
+# .spec.postBuild.substitute.storage_class: OpenShift StorageClass to use to create volumes.
+# .spec.postBuild.substitute.control_plane_availability: Availability of the contro plane. Valid only SingleReplica or HighAvailability
+# .spec.postBuild.substitute.worker_count: Number of Workers.
+# .spec.postBuild.substitute.worker_cores: CPU count of Workers.
+# .spec.postBuild.substitute.worker_memory: Memory size of Workers in Gi.
+# .spec.postBuild.substitute.worker_volume_size: Volume size of Workers in Gi.
+
+# Cluster resource
+apiVersion: kustomize.toolkit.fluxcd.io/v1
+kind: Kustomization
+metadata:
+ name: ${CLUSTER_KUSTOMIZATION_NAME}
+ namespace: managed-resources
+ labels:
+ cluster: ${CLUSTER_KUSTOMIZATION_NAME}
+spec:
+ dependsOn:
+ - name: ${CLUSTER_KUSTOMIZATION_NAME}-ns
+ commonMetadata:
+ labels:
+ cluster: ${CLUSTER_KUSTOMIZATION_NAME}
+ interval: 1h
+ retryInterval: 1m
+ timeout: 5m
+ sourceRef:
+ kind: GitRepository
+ name: sw-catalogs
+ namespace: flux-system
+ path: ./cloud-resources/openshift/manifests/cluster
+ prune: true
+ # force: true
+ wait: true
+ # Input parameters
+ postBuild:
+ substitute:
+ base_domain: ${BASE_DOMAIN}
+ cluster_name: ${CLUSTER_NAME}
+ cluster_project: ${CLUSTER_PROJECT}
+ hosted_cluster_project: ${HOSTED_CLUSTER_PROJECT}
+ etcd_volume_size: ${ETCD_VOLUME_SIZE}
+ openshift_release: ${OPENSHIFT_RELEASE}
+ storage_class: ${STORAGE_CLASS}
+ control_plane_availability: ${CONTROL_PLANE_AVAILABILITY}
+ worker_count: ${WORKER_COUNT}
+ worker_cores: ${WORKER_CORES}
+ worker_memory: ${WORKER_MEMORY}
+ worker_volume_size: ${WORKER_VOLUME_SIZE}
value: osm_contrib
- name: dry_run
value: "{{inputs.parameters.dry_run}}"
-# ------ end of commit transaction
\ No newline at end of file
+# ------ end of commit transaction
+