diff --git a/.catalog-onboard-pipeline.yaml b/.catalog-onboard-pipeline.yaml new file mode 100644 index 0000000..f15b649 --- /dev/null +++ b/.catalog-onboard-pipeline.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: v1 +offerings: + - name: deploy-arch-ibm-slz-was-operator + kind: solution + catalog_id: 7df1e4ca-d54c-4fd0-82ce-3d13247308cd + offering_id: 70e68cb4-7026-4329-9faa-8a1e56444aba + variations: + - name: standard + mark_ready: false + install_type: extension + pre_validation: "tests/scripts/pre-validation-slz-roks.sh" + post_validation: "tests/scripts/post-validation-slz-roks.sh" diff --git a/.github/settings.yml b/.github/settings.yml index f97a943..fbbda70 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -22,7 +22,7 @@ repository: # Uncomment this description property # and update the description to the current repo description. - # description: "" + description: "This module installs a WebSphere® Liberty operator and create an instance of WebSphere Liberty operator on IBM Cloud Red Hat OpenShift cluster on VPC Gen2." # Use a comma-separated list of topics to set on the repo (ensure not to use any caps in the topic string). topics: terraform, ibm-cloud, terraform-module diff --git a/.gitignore b/.gitignore index a7550ad..ee8c557 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,4 @@ terraform.rc # Visual Studio Code .vscode/ +*.code-workspace diff --git a/.releaserc b/.releaserc index 708916f..0085925 100644 --- a/.releaserc +++ b/.releaserc @@ -10,6 +10,9 @@ }], ["@semantic-release/exec", { "successCmd": "echo \"SEMVER_VERSION=${nextRelease.version}\" >> $GITHUB_ENV" + }], + ["@semantic-release/exec",{ + "publishCmd": "./ci/trigger-catalog-onboarding-pipeline.sh --version=v${nextRelease.version}" }] ] } diff --git a/README.md b/README.md index ff003c2..a3ac53c 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,27 @@ -# Terraform Modules Template Project +# WebSphere Liberty operator on Red Hat OpenShift VPC cluster module -[![Incubating (Not yet consumable)](https://img.shields.io/badge/status-Incubating%20(Not%20yet%20consumable)-red)](https://terraform-ibm-modules.github.io/documentation/#/badge-status) +[![Implemented (No quality checks)](https://img.shields.io/badge/Status-Implemented%20(No%20quality%20checks)-yellowgreen)](https://terraform-ibm-modules.github.io/documentation/#/badge-status) [![latest release](https://img.shields.io/github/v/release/terraform-ibm-modules/terraform-ibm-websphere-liberty-operator?logo=GitHub&sort=semver)](https://github.com/terraform-ibm-modules/terraform-ibm-websphere-liberty-operator/releases/latest) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) [![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com/) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) -TODO: Replace me with description of the module(s) in this repo +Use this module to install a WebSphere® Liberty operator and create an instance of WebSphere Liberty operator on IBM Cloud Red Hat OpenShift cluster on VPC Gen2. +For more information about the WebSphere Liberty operator refer to the official documentation avaiable [here](https://www.ibm.com/docs/en/was-liberty/core?topic=container-running-websphere-liberty-operator) ## Overview * [terraform-ibm-websphere-liberty-operator](#terraform-ibm-websphere-liberty-operator) * [Examples](./examples) - * [Basic example](./examples/basic) * [Complete example](./examples/complete) * [Contributing](#contributing) @@ -89,6 +89,12 @@ statement instead the previous block. | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.3.0, <1.6.0 | +| [external](#requirement\_external) | >=2.2.3, <3.0.0 | +| [helm](#requirement\_helm) | >= 2.8.0, <3.0.0 | +| [ibm](#requirement\_ibm) | >= 1.59.0, < 2.0.0 | +| [kubernetes](#requirement\_kubernetes) | >= 2.16.1, <3.0.0 | +| [null](#requirement\_null) | >= 3.2.1, < 4.0.0 | +| [time](#requirement\_time) | >= 0.9.1, < 1.0.0 | ### Modules @@ -96,15 +102,46 @@ No modules. ### Resources -No resources. +| Name | Type | +|------|------| +| [helm_release.ibm_operator_catalog](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | +| [helm_release.websphere_liberty_operator](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | +| [helm_release.websphere_liberty_operator_group](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | +| [helm_release.websphere_liberty_operator_sampleapp](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | +| [kubernetes_namespace.helm_release_operator_namespace](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource | +| [kubernetes_namespace.websphere_liberty_operator_namespace](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource | +| [kubernetes_namespace.websphere_liberty_sampleapp_namespace](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource | +| [null_resource.confirm_websphere_liberty_operator_operational](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [time_sleep.wait_catalog](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [time_sleep.wait_sampleapp](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [time_sleep.wait_websphere_liberty_operator](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [external_external.websphere_liberty_operator_sampleapp_url](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external) | data source | +| [ibm_container_cluster_config.cluster_config](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/data-sources/container_cluster_config) | data source | ### Inputs -No inputs. +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [add\_ibm\_operator\_catalog](#input\_add\_ibm\_operator\_catalog) | Flag to configure the IBM Operator Catalog in the cluster before installing the WebSphere Liberty Operator. Default is true | `bool` | `true` | no | +| [cluster\_config\_endpoint\_type](#input\_cluster\_config\_endpoint\_type) | Specify which type of endpoint to use for for cluster config access: 'default', 'private', 'vpe', 'link'. 'default' value will use the default endpoint of the cluster. | `string` | `"default"` | no | +| [cluster\_id](#input\_cluster\_id) | Id of the target IBM Cloud OpenShift Cluster | `string` | n/a | yes | +| [create\_ws\_liberty\_operator\_namespace](#input\_create\_ws\_liberty\_operator\_namespace) | Flag to create the namespace where to deploy the WebSphere Liberty Operator. Default to false | `bool` | `false` | no | +| [ibmcloud\_api\_key](#input\_ibmcloud\_api\_key) | APIkey that's associated with the account to use | `string` | `null` | no | +| [install\_wslo\_sampleapp](#input\_install\_wslo\_sampleapp) | Flag to deploy the WebSphere Liberty sample application. Default to false | `bool` | `false` | no | +| [operator\_helm\_release\_namespace](#input\_operator\_helm\_release\_namespace) | Namespace to deploy the helm releases. Default to liberty-operator-helm-release | `string` | `"liberty-operator"` | no | +| [region](#input\_region) | Cluster region | `string` | n/a | yes | +| [ws\_liberty\_operator\_namespace](#input\_ws\_liberty\_operator\_namespace) | Namespace to install the WebSphere Liberty Operator. Default to openshift-operators | `string` | `"openshift-operators"` | no | +| [ws\_liberty\_operator\_target\_namespace](#input\_ws\_liberty\_operator\_target\_namespace) | Namespace to be watched by the WebSphere Liberty Operator. Default to null (operator to watch all namespaces) | `string` | `null` | no | +| [wslo\_sampleapp\_name](#input\_wslo\_sampleapp\_name) | Application name to use for the WebSphere Liberty sample application | `string` | `"websphereliberty-app-sample"` | no | +| [wslo\_sampleapp\_namespace](#input\_wslo\_sampleapp\_namespace) | Namespace to deploy the WebSphere Liberty sample application | `string` | `"samplelibertyapp"` | no | ### Outputs -No outputs. +| Name | Description | +|------|-------------| +| [websphere\_liberty\_operator\_sampleapp\_url](#output\_websphere\_liberty\_operator\_sampleapp\_url) | WebSphere Liberty sample application URL | +| [ws\_liberty\_operator\_namespace](#output\_ws\_liberty\_operator\_namespace) | Namespace where the WebSphere Liberty operator is installed | +| [ws\_liberty\_operator\_target\_namespace](#output\_ws\_liberty\_operator\_target\_namespace) | Namespace watched by the WebSphere Liberty operator | diff --git a/chart/ibm-operator-catalog/.helmignore b/chart/ibm-operator-catalog/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/chart/ibm-operator-catalog/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/chart/ibm-operator-catalog/Chart.yaml b/chart/ibm-operator-catalog/Chart.yaml new file mode 100644 index 0000000..2ec4e9e --- /dev/null +++ b/chart/ibm-operator-catalog/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +name: ibm-websphere-liberty-operator +description: A Helm chart to configure the Operator Catalog source for the IBM operator catalog +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.0.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.0.0" diff --git a/chart/ibm-operator-catalog/templates/ibm-operator-catalog-source.yaml b/chart/ibm-operator-catalog/templates/ibm-operator-catalog-source.yaml new file mode 100644 index 0000000..6e83822 --- /dev/null +++ b/chart/ibm-operator-catalog/templates/ibm-operator-catalog-source.yaml @@ -0,0 +1,13 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: CatalogSource +metadata: + name: ibm-operator-catalog + namespace: openshift-marketplace +spec: + displayName: IBM Operator Catalog + publisher: IBM + sourceType: grpc + image: '{{ .Values.image.path }}:{{ required "IBM Operator catalog version must be provided" .Values.image.version }}' + updateStrategy: + registryPoll: + interval: 45m diff --git a/chart/ibm-operator-catalog/values.yaml b/chart/ibm-operator-catalog/values.yaml new file mode 100755 index 0000000..f499b50 --- /dev/null +++ b/chart/ibm-operator-catalog/values.yaml @@ -0,0 +1,5 @@ +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +image: + path: "icr.io/cpopen/ibm-operator-catalog" + version: "v1.25-20240202.161709-9DAF3E648@sha256:92e28be4af60f68c656f52b2445aafcc052fcd0390479b868c5b0ba2d465a25a" diff --git a/chart/websphere-liberty-operator-group/.helmignore b/chart/websphere-liberty-operator-group/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/chart/websphere-liberty-operator-group/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/chart/websphere-liberty-operator-group/Chart.yaml b/chart/websphere-liberty-operator-group/Chart.yaml new file mode 100644 index 0000000..3b3c66c --- /dev/null +++ b/chart/websphere-liberty-operator-group/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +name: ibm-websphere-liberty-operator +description: A Helm chart to configure the Operator Group for the IBM WebSphere Liberty Operator +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.0.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.0.0" diff --git a/chart/websphere-liberty-operator-group/templates/ibm-websphere-liberty-operator-group.yaml b/chart/websphere-liberty-operator-group/templates/ibm-websphere-liberty-operator-group.yaml new file mode 100644 index 0000000..868946a --- /dev/null +++ b/chart/websphere-liberty-operator-group/templates/ibm-websphere-liberty-operator-group.yaml @@ -0,0 +1,8 @@ +apiVersion: operators.coreos.com/v1alpha2 +kind: OperatorGroup +metadata: + name: ibm-websphere-liberty + namespace: {{ .Values.operatornamespace }} +spec: + targetNamespaces: + - {{ .Values.operatortargetnamespace }} diff --git a/chart/websphere-liberty-operator-group/values.yaml b/chart/websphere-liberty-operator-group/values.yaml new file mode 100755 index 0000000..09cd1a5 --- /dev/null +++ b/chart/websphere-liberty-operator-group/values.yaml @@ -0,0 +1,5 @@ +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +operatornamespace: openshift-operators +operatortargetnamespace: openshift-operators diff --git a/chart/websphere-liberty-operator-sampleapp/Chart.yaml b/chart/websphere-liberty-operator-sampleapp/Chart.yaml new file mode 100644 index 0000000..31bf613 --- /dev/null +++ b/chart/websphere-liberty-operator-sampleapp/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +name: ibm-websphere-liberty-operator-sampleapp +description: A Helm chart to a sample application for the IBM WebSphere Liberty Operator +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.0.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.0.0" diff --git a/chart/websphere-liberty-operator-sampleapp/templates/websphere-liberty-sample-app.yaml b/chart/websphere-liberty-operator-sampleapp/templates/websphere-liberty-sample-app.yaml new file mode 100644 index 0000000..e4d7546 --- /dev/null +++ b/chart/websphere-liberty-operator-sampleapp/templates/websphere-liberty-sample-app.yaml @@ -0,0 +1,14 @@ +apiVersion: liberty.websphere.ibm.com/v1 +kind: WebSphereLibertyApplication +metadata: + name: {{ .Values.application.name }} + namespace: {{ .Values.application.namespace }} +spec: + license: + accept: true + edition: IBM WebSphere Application Server + productEntitlementSource: Standalone + applicationImage: >- + {{ .Values.application.image.path }}:{{ required "Liberty sample app version must be provided" .Values.application.image.version }} + manageTLS: true + expose: true diff --git a/chart/websphere-liberty-operator-sampleapp/values.yaml b/chart/websphere-liberty-operator-sampleapp/values.yaml new file mode 100644 index 0000000..cf7d794 --- /dev/null +++ b/chart/websphere-liberty-operator-sampleapp/values.yaml @@ -0,0 +1,6 @@ +application: + name: websphereliberty-app-sample + namespace: samplelibertyapp + image: + path: "icr.io/appcafe/open-liberty/samples/getting-started" + version: "latest@sha256:d735c2ceae5945a0f20adcbcb04e55472d2520b6d1abb6d3049c8521234d3b7a" diff --git a/chart/websphere-liberty-operator/.helmignore b/chart/websphere-liberty-operator/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/chart/websphere-liberty-operator/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/chart/websphere-liberty-operator/Chart.yaml b/chart/websphere-liberty-operator/Chart.yaml new file mode 100644 index 0000000..83f8380 --- /dev/null +++ b/chart/websphere-liberty-operator/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +name: ibm-websphere-liberty-operator +description: A Helm chart to configure the Subscription for the IBM WebSphere Liberty Operator +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.0.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.0.0" diff --git a/chart/websphere-liberty-operator/scripts/uninstall-operator-resources.sh b/chart/websphere-liberty-operator/scripts/uninstall-operator-resources.sh new file mode 100755 index 0000000..3bfe44f --- /dev/null +++ b/chart/websphere-liberty-operator/scripts/uninstall-operator-resources.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +## Needed to delete resources (CSVs and installPlans) created by the OLM outside of the Terraform scope + +operator_names=( "ibm-websphere-liberty" ) + +echo "Fetching and deleting CSVs and installPlans for IBM WebSphere Liberty Operator" + +for i in "${operator_names[@]}" +do + CSV=$(kubectl get subscription "$i" -o jsonpath="{$.status.installedCSV}" -n "$1") + + if [ -n "$CSV" ] + then + echo "Deleting CSV ${CSV}" + kubectl delete csv "$CSV" -n "$1" + fi + + IP=$(kubectl get installPlan -n "$1" | grep "${i}" | awk '{print $1}') + + if [ -n "$IP" ] + then + echo "Deleting installPlan ${IP}" + kubectl delete installPlan "$IP" -n "$1" + fi +done diff --git a/chart/websphere-liberty-operator/templates/ibm-websphere-liberty-operator-subscription.yaml b/chart/websphere-liberty-operator/templates/ibm-websphere-liberty-operator-subscription.yaml new file mode 100644 index 0000000..d95e43d --- /dev/null +++ b/chart/websphere-liberty-operator/templates/ibm-websphere-liberty-operator-subscription.yaml @@ -0,0 +1,11 @@ +# ibm-websphere-liberty-operator-subscription.yaml +apiVersion: operators.coreos.com/v1alpha1 +kind: Subscription +metadata: + name: ibm-websphere-liberty + namespace: {{ .Values.operatornamespace }} +spec: + installPlanApproval: Manual + name: ibm-websphere-liberty + source: ibm-operator-catalog + sourceNamespace: openshift-marketplace diff --git a/chart/websphere-liberty-operator/templates/uninstall-hook-config-map.yaml b/chart/websphere-liberty-operator/templates/uninstall-hook-config-map.yaml new file mode 100644 index 0000000..3e62abd --- /dev/null +++ b/chart/websphere-liberty-operator/templates/uninstall-hook-config-map.yaml @@ -0,0 +1,15 @@ +# The OLM created csv objects on the cluster during install - there is a need to clean up csv created by the OLM, in addition to removing the subscription +# See https://olm.operatorframework.io/docs/tasks/uninstall-operator/#combine-steps-2-and-3 for context + +apiVersion: v1 +kind: ConfigMap +metadata: + name: wslo-uninstall-scripts + namespace: {{ .Values.operatornamespace }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed + "helm.sh/hook-weight": "3" +data: + uninstall-operator-resources.sh: |- +{{ .Files.Get "scripts/uninstall-operator-resources.sh" | indent 4}} diff --git a/chart/websphere-liberty-operator/templates/uninstall-hook-crb.yaml b/chart/websphere-liberty-operator/templates/uninstall-hook-crb.yaml new file mode 100644 index 0000000..db66a58 --- /dev/null +++ b/chart/websphere-liberty-operator/templates/uninstall-hook-crb.yaml @@ -0,0 +1,36 @@ +# The OLM created csv objects on the cluster during install - there is a need to clean up csv created by the OLM, in addition to removing the subscription +# See https://olm.operatorframework.io/docs/tasks/uninstall-operator/#combine-steps-2-and-3 for context + +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: wslo-uninstall-hook-role-binding-edit + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed + "helm.sh/hook-weight": "2" +subjects: + - kind: ServiceAccount + name: wslo-uninstall-hook-role-sa + namespace: {{ .Values.operatornamespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: aggregate-olm-edit +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: wslo-uninstall-hook-role-binding-view + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed + "helm.sh/hook-weight": "2" +subjects: + - kind: ServiceAccount + name: wslo-uninstall-hook-role-sa + namespace: {{ .Values.operatornamespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: aggregate-olm-view diff --git a/chart/websphere-liberty-operator/templates/uninstall-hook-job.yaml b/chart/websphere-liberty-operator/templates/uninstall-hook-job.yaml new file mode 100644 index 0000000..ba0eaa2 --- /dev/null +++ b/chart/websphere-liberty-operator/templates/uninstall-hook-job.yaml @@ -0,0 +1,58 @@ +# The OLM created csv objects on the cluster during install - there is a need to clean up csv created by the OLM, in addition to removing the subscription +# See https://olm.operatorframework.io/docs/tasks/uninstall-operator/#combine-steps-2-and-3 for context + +apiVersion: batch/v1 +kind: Job +metadata: + name: wslo-uninstall-hook + namespace: {{ .Values.operatornamespace }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed + "helm.sh/hook-weight": "4" + checkov.io/skip1: CKV_K8S_21 + checkov.io/skip2: CKV_K8S_30 + checkov.io/skip3: CKV_K8S_28 + checkov.io/skip4: CKV_K8S_22 + checkov.io/skip5: CKV_K8S_20 + checkov.io/skip6: CKV_K8S_37 + checkov.io/skip7: CKV_K8S_23 + checkov.io/skip8: CKV_K8S_38 + checkov.io/skip9: CKV_K8S_29 + checkov.io/skip10: CKV_K8S_40 + checkov.io/skip11: CKV_K8S_31 + checkov.io/skip12: CKV_K8S_9 + checkov.io/skip13: CKV_K8S_16 + checkov.io/skip14: CKV_K8S_8 + checkov.io/skip15: CKV_K8S_43 +spec: + template: + metadata: + name: wslo-uninstall-hook + spec: + restartPolicy: Never + serviceAccountName: wslo-uninstall-hook-role-sa + volumes: + - name: scripts + configMap: + name: wslo-uninstall-scripts + defaultMode: 0777 + containers: + - name: wslo-uninstall-hook-job + image: "icr.io/goldeneye_images/ubi8-cluster-tools:stable" + # Deliberately always pull to grab latest image at the time when uninstall hook executed, + # which may be a long time (multi months) after chart was deployed + imagePullPolicy: Always + command: ["/bin/sh"] + args: ["-xc", "/scripts/uninstall-operator-resources.sh {{ .Values.operatornamespace }}"] + volumeMounts: + - mountPath: /scripts + name: scripts + readOnly: true + resources: + limits: + cpu: 50m + memory: 50Mi + requests: + cpu: 50m + memory: 50Mi diff --git a/chart/websphere-liberty-operator/templates/uninstall-hook-sa.yaml b/chart/websphere-liberty-operator/templates/uninstall-hook-sa.yaml new file mode 100644 index 0000000..05ee5c7 --- /dev/null +++ b/chart/websphere-liberty-operator/templates/uninstall-hook-sa.yaml @@ -0,0 +1,12 @@ +# The OLM created csv objects on the cluster during install - there is a need to clean up csv created by the OLM, in addition to removing the subscription +# See https://olm.operatorframework.io/docs/tasks/uninstall-operator/#combine-steps-2-and-3 for context + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: wslo-uninstall-hook-role-sa + namespace: {{ .Values.operatornamespace }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed + "helm.sh/hook-weight": "1" diff --git a/chart/websphere-liberty-operator/values.yaml b/chart/websphere-liberty-operator/values.yaml new file mode 100755 index 0000000..5ec3366 --- /dev/null +++ b/chart/websphere-liberty-operator/values.yaml @@ -0,0 +1,4 @@ +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +operatornamespace: openshift-operators diff --git a/cra-tf-validate-ignore-rules.json b/cra-tf-validate-ignore-rules.json index adbff6e..008b080 100644 --- a/cra-tf-validate-ignore-rules.json +++ b/cra-tf-validate-ignore-rules.json @@ -1,3 +1,10 @@ { - "scc_rules": [] + "scc_rules": [ + { + "scc_rule_id": "rule-64c0bea0-8760-4a6b-a56c-ee375a48961e", + "description": "Check whether Virtual Private Cloud (VPC) has no public gateways attached", + "ignore_reason": "Need public network access to collect liberty operator images", + "is_valid": true + } + ] } diff --git a/examples/basic/README.md b/examples/basic/README.md deleted file mode 100644 index 86eab8e..0000000 --- a/examples/basic/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Basic example - - - -An end-to-end basic example that will provision the following: -- A new resource group if one is not passed in. -- A new Cloud Object Storage instance. diff --git a/examples/basic/main.tf b/examples/basic/main.tf deleted file mode 100644 index 4aeca62..0000000 --- a/examples/basic/main.tf +++ /dev/null @@ -1,24 +0,0 @@ -######################################################################################################################## -# Resource group -######################################################################################################################## - -module "resource_group" { - source = "terraform-ibm-modules/resource-group/ibm" - version = "1.1.4" - # if an existing resource group is not set (null) create a new one using prefix - resource_group_name = var.resource_group == null ? "${var.prefix}-resource-group" : null - existing_resource_group_name = var.resource_group -} - -######################################################################################################################## -# COS instance -######################################################################################################################## - -resource "ibm_resource_instance" "cos_instance" { - name = "${var.prefix}-cos" - resource_group_id = module.resource_group.resource_group_id - service = "cloud-object-storage" - plan = "standard" - location = "global" - tags = var.resource_tags -} diff --git a/examples/basic/outputs.tf b/examples/basic/outputs.tf deleted file mode 100644 index 04b196e..0000000 --- a/examples/basic/outputs.tf +++ /dev/null @@ -1,18 +0,0 @@ -######################################################################################################################## -# Outputs -######################################################################################################################## - -output "cos_instance_id" { - description = "COS instance id" - value = ibm_resource_instance.cos_instance.id -} - -output "resource_group_name" { - description = "Resource group name" - value = module.resource_group.resource_group_name -} - -output "resource_group_id" { - description = "Resource group ID" - value = module.resource_group.resource_group_id -} diff --git a/examples/basic/version.tf b/examples/basic/version.tf deleted file mode 100644 index 46915a6..0000000 --- a/examples/basic/version.tf +++ /dev/null @@ -1,12 +0,0 @@ -terraform { - required_version = ">= 1.3.0, <1.6.0" - - # Ensure that there is always 1 example locked into the lowest provider version of the range defined in the main - # module's version.tf (usually a basic example), and 1 example that will always use the latest provider version. - required_providers { - ibm = { - source = "IBM-Cloud/ibm" - version = "1.49.0" - } - } -} diff --git a/examples/complete/README.md b/examples/complete/README.md index 139f8dd..2efdcfa 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -1,4 +1,7 @@ # Complete example - - +An end-to-end complete example that will provision the following: +- A new resource group if one is not passed in. +- A new VPC with 3 subnets and a new OpenShift cluster in the VPC with 3 workers pools +- The IBM WebSphere Liberty operator in the default operator namespace +- The IBM WebSphere Liberty sample app diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 558c210..1f55436 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -1,3 +1,120 @@ +######################################################################################################################## +# Resource Group +######################################################################################################################## + +module "resource_group" { + source = "terraform-ibm-modules/resource-group/ibm" + version = "1.1.4" + # if an existing resource group is not set (null) create a new one using prefix + resource_group_name = var.resource_group == null ? "${var.prefix}-resource-group" : null + existing_resource_group_name = var.resource_group +} + +######################################################################################################################## +# VPC +######################################################################################################################## + +resource "ibm_is_vpc" "vpc" { + name = "${var.prefix}-vpc" + resource_group = module.resource_group.resource_group_id + address_prefix_management = "auto" + tags = var.resource_tags +} + +# public gws +resource "ibm_is_public_gateway" "gateway" { + for_each = toset(["1", "2", "3"]) + name = "${var.prefix}-gateway-${each.key}" + vpc = ibm_is_vpc.vpc.id + resource_group = module.resource_group.resource_group_id + zone = "${var.region}-${each.key}" +} + + +resource "ibm_is_subnet" "cluster_subnets" { + for_each = toset(["1", "2", "3"]) + name = "${var.prefix}-subnet-${each.key}" + vpc = ibm_is_vpc.vpc.id + resource_group = module.resource_group.resource_group_id + zone = "${var.region}-${each.key}" + total_ipv4_address_count = 256 + public_gateway = ibm_is_public_gateway.gateway[each.key].id +} + ############################################################################## -# Complete example +# OCP CLUSTER ############################################################################## + +locals { + + subnets = [ + for subnet in ibm_is_subnet.cluster_subnets : + { + id = subnet.id + zone = subnet.zone + cidr_block = subnet.ipv4_cidr_block + } + ] + + # mapping of cluster worker pool names to subnets + cluster_vpc_subnets = { + zone-1 = local.subnets, + zone-2 = local.subnets, + zone-3 = local.subnets + } + + worker_pools = [ + { + subnet_prefix = "zone-1" + pool_name = "default" # ibm_container_vpc_cluster automatically names default pool "default" (See https://github.com/IBM-Cloud/terraform-provider-ibm/issues/2849) + machine_type = "bx2.4x16" + workers_per_zone = 1 + labels = {} + }, + { + subnet_prefix = "zone-2" + pool_name = "zone-2" + machine_type = "bx2.4x16" + workers_per_zone = 1 + labels = { "dedicated" : "edge" } + }, + { + subnet_prefix = "zone-3" + pool_name = "zone-3" + machine_type = "bx2.4x16" + workers_per_zone = 1 + labels = { "dedicated" : "transit" } + } + ] +} + +module "ocp_base" { + depends_on = [ibm_is_vpc.vpc, ibm_is_subnet.cluster_subnets, ibm_is_public_gateway.gateway] + source = "terraform-ibm-modules/base-ocp-vpc/ibm" + version = "3.10.1" + cluster_name = "${var.prefix}-cluster" + cos_name = "${var.prefix}-cos" + resource_group_id = module.resource_group.resource_group_id + region = var.region + force_delete_storage = true + vpc_id = ibm_is_vpc.vpc.id + vpc_subnets = local.cluster_vpc_subnets + worker_pools = local.worker_pools + tags = var.resource_tags + ibmcloud_api_key = var.ibmcloud_api_key + ocp_version = var.ocp_version +} + + +############################################################################## +# IBM WebSphere Liberty operator deployment on the OCP cluster +############################################################################## + +module "websphere_liberty_operator" { + source = "../.." + region = var.region + cluster_id = module.ocp_base.cluster_id + create_ws_liberty_operator_namespace = false + install_wslo_sampleapp = true + ibmcloud_api_key = var.ibmcloud_api_key +} diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index addadea..526e37f 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -1,23 +1,18 @@ -############################################################################## +######################################################################################################################## # Outputs -############################################################################## +######################################################################################################################## -output "region" { - description = "The region all resources were provisioned in" - value = var.region -} - -output "prefix" { - description = "The prefix used to name all provisioned resources" - value = var.prefix +output "resource_group_name" { + description = "Resource group name" + value = module.resource_group.resource_group_name } -output "resource_group_name" { - description = "The name of the resource group used" - value = var.resource_group +output "cluster_id" { + description = "Cluster ID" + value = module.ocp_base.cluster_id } -output "resource_tags" { - description = "List of resource tags" - value = var.resource_tags +output "websphere_liberty_sampleapp_url" { + description = "Url of the IBM WebSphere Liberty sample application" + value = module.websphere_liberty_operator.websphere_liberty_operator_sampleapp_url } diff --git a/examples/complete/provider.tf b/examples/complete/provider.tf index 2080946..9d3071e 100644 --- a/examples/complete/provider.tf +++ b/examples/complete/provider.tf @@ -1,8 +1,29 @@ ############################################################################## -# Provider config +# Config providers ############################################################################## +# IBM provider used to provision IBM Cloud resources provider "ibm" { ibmcloud_api_key = var.ibmcloud_api_key region = var.region } + +# Init cluster config for helm and kubernetes providers +data "ibm_container_cluster_config" "cluster_config" { + cluster_name_id = module.ocp_base.cluster_id + resource_group_id = module.resource_group.resource_group_id +} + +# Helm provider used to deploy cluster-proxy and observability agents +provider "helm" { + kubernetes { + host = data.ibm_container_cluster_config.cluster_config.host + token = data.ibm_container_cluster_config.cluster_config.token + } +} + +# Kubernetes provider used to create kube namespace(s) +provider "kubernetes" { + host = data.ibm_container_cluster_config.cluster_config.host + token = data.ibm_container_cluster_config.cluster_config.token +} diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index 170a5ab..738b0c6 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -1,19 +1,25 @@ variable "ibmcloud_api_key" { type = string - description = "The IBM Cloud API Key" + description = "The IBM Cloud API Token" sensitive = true } +variable "prefix" { + type = string + description = "Prefix for name of all resource created by this example" + default = "wslop" +} + variable "region" { type = string description = "Region to provision all resources created by this example" - default = "us-south" + default = "au-syd" } -variable "prefix" { +variable "ocp_version" { + description = "The version of the OpenShift cluster that should be provisioned (format 4.x)" type = string - description = "Prefix to append to all resources created by this example" - default = "complete" + default = null } variable "resource_group" { diff --git a/examples/complete/version.tf b/examples/complete/version.tf index 5adb5b5..67dd3a2 100644 --- a/examples/complete/version.tf +++ b/examples/complete/version.tf @@ -1,12 +1,19 @@ terraform { required_version = ">= 1.3.0, <1.6.0" - - # Ensure that there is always 1 example locked into the lowest provider version of the range defined in the main - # module's version.tf (usually a basic example), and 1 example that will always use the latest provider version. required_providers { + # Pin to the lowest provider version of the range defined in the main module to ensure lowest version still works + # OCP all inclusive requires 1.56.1, so breaking pin to lowest provider version. Note: PR tests include multiple-control-plans which is pinned ibm = { source = "IBM-Cloud/ibm" - version = ">= 1.49.0, < 2.0.0" + version = ">= 1.59.0" + } + helm = { + source = "hashicorp/helm" + version = "2.8.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.16.1" } } } diff --git a/extensions/landing-zone/README.md b/extensions/landing-zone/README.md new file mode 100644 index 0000000..221c490 --- /dev/null +++ b/extensions/landing-zone/README.md @@ -0,0 +1,3 @@ +### # Client-To-Site VPN extension for landing zone + +Tutorial: TBD diff --git a/extensions/landing-zone/catalogValidationValues.json.template b/extensions/landing-zone/catalogValidationValues.json.template new file mode 100644 index 0000000..f48a7e3 --- /dev/null +++ b/extensions/landing-zone/catalogValidationValues.json.template @@ -0,0 +1,3 @@ +{ + "ibmcloud_api_key": $VALIDATION_APIKEY +} diff --git a/extensions/landing-zone/main.tf b/extensions/landing-zone/main.tf new file mode 100644 index 0000000..5294cd0 --- /dev/null +++ b/extensions/landing-zone/main.tf @@ -0,0 +1,25 @@ +############################################################################## +# IBM WebSphere Liberty operator deployment on the OCP cluster +############################################################################## + +data "ibm_container_cluster_config" "cluster_config" { + cluster_name_id = var.cluster_id + # config_dir = "../../kubeconfig" + endpoint_type = var.cluster_config_endpoint_type != "default" ? var.cluster_config_endpoint_type : null # null represents default +} + +module "websphere_liberty_operator" { + source = "../.." + ibmcloud_api_key = var.ibmcloud_api_key + region = var.region + cluster_id = var.cluster_id + add_ibm_operator_catalog = var.add_ibm_operator_catalog + create_ws_liberty_operator_namespace = var.create_ws_liberty_operator_namespace + ws_liberty_operator_namespace = var.ws_liberty_operator_namespace + ws_liberty_operator_target_namespace = var.ws_liberty_operator_target_namespace + cluster_config_endpoint_type = var.cluster_config_endpoint_type + install_wslo_sampleapp = var.install_wslo_sampleapp + wslo_sampleapp_name = var.wslo_sampleapp_name + wslo_sampleapp_namespace = var.wslo_sampleapp_namespace + operator_helm_release_namespace = var.operator_helm_release_namespace +} diff --git a/examples/basic/provider.tf b/extensions/landing-zone/outputs.tf similarity index 64% rename from examples/basic/provider.tf rename to extensions/landing-zone/outputs.tf index 84b6985..a75f2bd 100644 --- a/examples/basic/provider.tf +++ b/extensions/landing-zone/outputs.tf @@ -1,8 +1,8 @@ ######################################################################################################################## -# Provider config +# Outputs ######################################################################################################################## -provider "ibm" { - ibmcloud_api_key = var.ibmcloud_api_key - region = var.region +output "websphere_liberty_operator" { + description = "Resource group name" + value = module.websphere_liberty_operator } diff --git a/extensions/landing-zone/provider.tf b/extensions/landing-zone/provider.tf new file mode 100644 index 0000000..494c945 --- /dev/null +++ b/extensions/landing-zone/provider.tf @@ -0,0 +1,20 @@ +############################################################################## +# Config providers +############################################################################## + +provider "ibm" { + ibmcloud_api_key = var.ibmcloud_api_key + region = var.region +} + +provider "helm" { + kubernetes { + host = data.ibm_container_cluster_config.cluster_config.host + token = data.ibm_container_cluster_config.cluster_config.token + } +} + +provider "kubernetes" { + host = data.ibm_container_cluster_config.cluster_config.host + token = data.ibm_container_cluster_config.cluster_config.token +} diff --git a/extensions/landing-zone/variables.tf b/extensions/landing-zone/variables.tf new file mode 100644 index 0000000..ece0cce --- /dev/null +++ b/extensions/landing-zone/variables.tf @@ -0,0 +1,76 @@ +variable "ibmcloud_api_key" { + type = string + description = "APIkey associated with the account to use" + sensitive = true +} + +variable "region" { + type = string + description = "Region to provision all resources created by this solution" + default = "au-syd" +} + +variable "cluster_id" { + type = string + description = "Id of the target IBM Cloud OpenShift Cluster" + nullable = false +} + +variable "operator_helm_release_namespace" { + type = string + description = "Namespace to deploy the helm releases. Default to liberty-operator-helm-release" + default = "liberty-operator-helm-release" +} + +variable "add_ibm_operator_catalog" { + type = bool + description = "Flag to configure the IBM Operator Catalog in the cluster before installing the WebSphere Liberty Operator. Default is true" + default = true +} + +variable "create_ws_liberty_operator_namespace" { + type = bool + description = "Flag to create the namespace where to deploy the WebSphere Liberty Operator. Default to false" + default = false +} + +variable "ws_liberty_operator_namespace" { + type = string + description = "Namespace to install the WebSphere Liberty Operator. Default to openshift-operators" + default = "openshift-operators" +} + +variable "ws_liberty_operator_target_namespace" { + type = string + description = "Namespace to be watched by the WebSphere Liberty Operator. Default to null (operator to watch all namespaces)" + default = null +} + +variable "cluster_config_endpoint_type" { + description = "Specify which type of endpoint to use for for cluster config access: 'default', 'private', 'vpe', 'link'. 'default' value will use the default endpoint of the cluster." + type = string + default = "default" + nullable = false # use default if null is passed in + validation { + error_message = "Invalid Endpoint Type! Valid values are 'default', 'private', 'vpe', or 'link'" + condition = contains(["default", "private", "vpe", "link"], var.cluster_config_endpoint_type) + } +} + +variable "install_wslo_sampleapp" { + description = "Flag to deploy the WebSphere Liberty sample application. Default to false" + type = bool + default = false +} + +variable "wslo_sampleapp_name" { + description = "Application name to use for the WebSphere Liberty sample application" + type = string + default = "websphereliberty-app-sample" +} + +variable "wslo_sampleapp_namespace" { + description = "Namespace to deploy the WebSphere Liberty sample application" + type = string + default = "samplelibertyapp" +} diff --git a/extensions/landing-zone/version.tf b/extensions/landing-zone/version.tf new file mode 100644 index 0000000..59a1a3d --- /dev/null +++ b/extensions/landing-zone/version.tf @@ -0,0 +1,19 @@ +terraform { + required_version = ">= 1.3.0, <1.6.0" + required_providers { + # Pin to the lowest provider version of the range defined in the main module to ensure lowest version still works + # OCP all inclusive requires 1.56.1, so breaking pin to lowest provider version. Note: PR tests include multiple-control-plans which is pinned + ibm = { + source = "IBM-Cloud/ibm" + version = "1.62.0" + } + helm = { + source = "hashicorp/helm" + version = "2.8.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.16.1" + } + } +} diff --git a/ibm_catalog.json b/ibm_catalog.json new file mode 100644 index 0000000..11d5341 --- /dev/null +++ b/ibm_catalog.json @@ -0,0 +1,120 @@ +{ + "products": [ + { + "name": "deploy-arch-ibm-slz-was-operator", + "label": "WebSphere Liberty operator add-on for the landing zone", + "product_kind": "solution", + "tags": [ + "ibm_created", + "target_terraform", + "terraform", + "reference_architecture", + "solution" + ], + "keywords": [ + "vpc", + "slz", + "IaC", + "infrastructure as code", + "terraform", + "solution", + "WAS", + "Operator", + "websphere liberty operator", + "websphere operator", + "was liberty operator", + "was operator" + ], + "short_description": "Installs the WebSphere (WAS) Liberty operator on the landing zone (SLZ).", + "long_description": "Installs the WebSphere (WAS) Liberty operator on the landing zone (SLZ).", + "offering_docs_url": "https://github.com/terraform-ibm-modules/terraform-ibm-websphere-liberty-operator/blob/main/README.md", + "offering_icon_url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-websphere-liberty-operator/main/images/Websphere-icon.svg", + "provider_name": "IBM", + "features": [ + { + "description": "Supports configuring the marketplace Catalog Source for the IBM Operators catalog on existing cluster.", + "title": "Configures Catalog Source for the IBM Operators catalog on existing cluster" + }, + { + "description": "Supports configuring the Operator Group for the IBM WebSphere Liberty Operator on existing cluster.", + "title": "Configures the Operator Group for the IBM WebSphere Liberty Operator on existing cluster." + }, + { + "description": "Supports installing the IBM WebSphere Liberty Operator on existing cluster.", + "title": "Installs the IBM WebSphere Liberty Operator on existing cluster." + }, + { + "description": "Supports installing the IBM WebSphere Liberty Operator sample application on existing cluster.", + "title": "Installs the IBM WebSphere Liberty Operator sample application on existing cluster.." + } + ], + "flavors": [ + { + "label": "Standard", + "name": "standard", + "install_type": "extension", + "working_directory": "extensions/landing-zone", + "dependencies": [ + { + "flavors": [ + "standard" + ], + "id": "95fccffc-ae3b-42df-b6d9-80be5914d852-global", + "name": "deploy-arch-ibm-slz-ocp", + "version": "v5.1.1-rc" + } + ], + "configuration": [ + { + "custom_config": { + "config_constraints": { + "generationType": "2" + }, + "grouping": "deployment", + "original_grouping": "deployment", + "type": "vpc_region" + }, + "key": "region", + "required": true + } + ], + "architecture": { + "descriptions": "", + "features": [ + { + "title": "Works with the landing zone", + "description": "Yes" + }, + { + "title": "Installs catalog source the IBM Operator catalog on the existing cluster", + "description": "Yes" + }, + { + "title": "Supports configuring the Operator Group for the IBM WebSphere Liberty Operator on existing cluster", + "description": "Yes" + }, + { + "title": "Supports installing the IBM WebSphere Liberty Operator on existing cluster", + "description": "Yes" + }, + { + "title": "Supports installing the IBM WebSphere Liberty Operator sample application on existing cluster", + "description": "Yes" + } + ], + "diagrams": [ + { + "diagram": { + "caption": "Websphere installation on a landing zone VPC cluster.", + "url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-websphere-liberty-operator/main/reference-architecture/was_operator.svg", + "type": "image/svg+xml" + }, + "description": "Websphere installation on a landing zone VPC cluster." + } + ] + } + } + ] + } + ] +} diff --git a/images/Websphere-icon.svg b/images/Websphere-icon.svg new file mode 100644 index 0000000..70d00cd --- /dev/null +++ b/images/Websphere-icon.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kubeconfig/.gitignore b/kubeconfig/.gitignore new file mode 100644 index 0000000..632a28f --- /dev/null +++ b/kubeconfig/.gitignore @@ -0,0 +1,6 @@ +# Ignore everything +* + +# But not these files... +!.gitignore +!README.md diff --git a/kubeconfig/README.md b/kubeconfig/README.md new file mode 100644 index 0000000..dff9dd4 --- /dev/null +++ b/kubeconfig/README.md @@ -0,0 +1,2 @@ +This directory must exist in source control so the `ibm_container_cluster_config` data lookup can use it to place the +config.yml used to connect to a kubernetes cluster (See https://github.ibm.com/GoldenEye/issues/issues/552). diff --git a/main.tf b/main.tf index 0b919ea..444948f 100644 --- a/main.tf +++ b/main.tf @@ -1,3 +1,280 @@ -/******************************************************************** -This file is used to implement the ROOT module. -*********************************************************************/ +locals { + # sleep times definition + sleep_time_catalog_create = "60s" + sleep_time_operator_create = "120s" + sleep_time_sampleapp_create = "30s" + + # helm chart names + ibm_operator_catalog_chart = "ibm-operator-catalog" + websphere_liberty_operator_chart = "websphere-liberty-operator" + websphere_liberty_operator_group_chart = "websphere-liberty-operator-group" + websphere_liberty_operator_sampleapp_chart = "websphere-liberty-operator-sampleapp" + + # validation of ws_liberty_operator_target_namespace - if null the value of ws_liberty_operator_namespace must be equal to "openshift-operators" https://www.ibm.com/docs/en/was-liberty/core?topic=operator-installing-red-hat-openshift-cli#in-t-cli__install-op-cli__title__1 + default_liberty_operator_namespace = "openshift-operators" + operator_target_namespace_cnd = var.ws_liberty_operator_target_namespace == null && var.ws_liberty_operator_namespace != local.default_liberty_operator_namespace + operator_target_namespace_msg = "if input var ws_liberty_operator_target_namespace is null the value of ws_liberty_operator_namespace must be equal to ${local.default_liberty_operator_namespace}" + # tflint-ignore: terraform_unused_declarations + operator_target_namespace_chk = regex("^${local.operator_target_namespace_msg}$", (!local.operator_target_namespace_cnd ? local.operator_target_namespace_msg : "")) +} + +data "ibm_container_cluster_config" "cluster_config" { + cluster_name_id = var.cluster_id + config_dir = "${path.module}/kubeconfig" + endpoint_type = var.cluster_config_endpoint_type != "default" ? var.cluster_config_endpoint_type : null +} + +# creating the namespace to deploy the helm releases to install the WebSphere Liberty Operator +resource "kubernetes_namespace" "helm_release_operator_namespace" { + metadata { + name = var.operator_helm_release_namespace + } + + timeouts { + delete = "30m" + } + + lifecycle { + ignore_changes = [ + metadata[0].annotations, + metadata[0].labels + ] + } +} + +locals { + ibm_operator_catalog_version = "v1.25-20240202.161709-9DAF3E648@sha256:92e28be4af60f68c656f52b2445aafcc052fcd0390479b868c5b0ba2d465a25a" # datasource: icr.io/cpopen/ibm-operator-catalog + ibm_operator_catalog_path = "icr.io/cpopen/ibm-operator-catalog" +} + +# if add_ibm_operator_catalog is true going on with adding the IBM Operator Catalog source +resource "helm_release" "ibm_operator_catalog" { + depends_on = [kubernetes_namespace.helm_release_operator_namespace] + count = var.add_ibm_operator_catalog == true ? 1 : 0 + + name = "ibm-operator-catalog-helm-release" + chart = "${path.module}/chart/${local.ibm_operator_catalog_chart}" + namespace = var.operator_helm_release_namespace + create_namespace = false + timeout = 300 + # dependency_update = true + # force_update = false + force_update = true + cleanup_on_fail = false + wait = true + recreate_pods = true + + disable_openapi_validation = false + + set { + name = "image.path" + type = "string" + value = local.ibm_operator_catalog_path + } + set { + name = "image.version" + type = "string" + value = local.ibm_operator_catalog_version + } +} + +# waiting for the catalog to be configured and correctly pulled +resource "time_sleep" "wait_catalog" { + depends_on = [helm_release.ibm_operator_catalog[0]] + count = var.add_ibm_operator_catalog == true ? 1 : 0 + + create_duration = local.sleep_time_catalog_create +} + +# if ws_liberty_operator_target_namespace != null the operator group must be created +resource "helm_release" "websphere_liberty_operator_group" { + count = var.ws_liberty_operator_target_namespace != null ? 1 : 0 + depends_on = [time_sleep.wait_catalog[0], kubernetes_namespace.helm_release_operator_namespace] + + name = "websphere-liberty-operator-group-helm-release" + chart = "${path.module}/chart/${local.websphere_liberty_operator_group_chart}" + namespace = var.operator_helm_release_namespace + create_namespace = false + timeout = 300 + # dependency_update = true + force_update = true + # force_update = false + cleanup_on_fail = false + wait = true + recreate_pods = true + + disable_openapi_validation = false + + set { + name = "operatornamespace" + type = "string" + value = var.ws_liberty_operator_namespace + } + + set { + name = "operatortargetnamespace" + type = "string" + value = var.ws_liberty_operator_target_namespace + } + +} + +resource "kubernetes_namespace" "websphere_liberty_operator_namespace" { + count = var.create_ws_liberty_operator_namespace == true ? 1 : 0 + + metadata { + name = var.ws_liberty_operator_namespace + } + + timeouts { + delete = "30m" + } + + lifecycle { + ignore_changes = [ + metadata[0].annotations, + metadata[0].labels + ] + } +} + +resource "helm_release" "websphere_liberty_operator" { + depends_on = [time_sleep.wait_catalog[0], helm_release.websphere_liberty_operator_group[0], kubernetes_namespace.websphere_liberty_operator_namespace[0]] + + name = "websphere-liberty-operator-helm-release" + chart = "${path.module}/chart/${local.websphere_liberty_operator_chart}" + namespace = var.operator_helm_release_namespace + create_namespace = false + timeout = 300 + # dependency_update = true + # force_update = false + force_update = true + cleanup_on_fail = false + wait = true + recreate_pods = true + + disable_openapi_validation = false + + set { + name = "operatornamespace" + type = "string" + value = var.ws_liberty_operator_namespace + } + + provisioner "local-exec" { + command = "${path.module}/scripts/approve-install-plan.sh ${var.ws_liberty_operator_namespace}" + interpreter = ["/bin/bash", "-c"] + environment = { + KUBECONFIG = data.ibm_container_cluster_config.cluster_config.config_file_path + } + } +} + +resource "time_sleep" "wait_websphere_liberty_operator" { + depends_on = [helm_release.websphere_liberty_operator] + + create_duration = local.sleep_time_operator_create +} + +############################################################################## +# Confirm websphere operator is operational +############################################################################## + +resource "null_resource" "confirm_websphere_liberty_operator_operational" { + + depends_on = [time_sleep.wait_websphere_liberty_operator] + + provisioner "local-exec" { + command = "${path.module}/scripts/confirm-wsloperator-operational.sh ${var.ws_liberty_operator_namespace}" + interpreter = ["/bin/bash", "-c"] + environment = { + KUBECONFIG = data.ibm_container_cluster_config.cluster_config.config_file_path + } + } +} + +resource "kubernetes_namespace" "websphere_liberty_sampleapp_namespace" { + depends_on = [null_resource.confirm_websphere_liberty_operator_operational] + count = var.install_wslo_sampleapp == true ? 1 : 0 + + metadata { + name = var.wslo_sampleapp_namespace + } + + timeouts { + delete = "30m" + } + + lifecycle { + ignore_changes = [ + metadata[0].annotations, + metadata[0].labels + ] + } +} + +locals { + websphere_liberty_operator_sampleapp_image_path = "icr.io/appcafe/open-liberty/samples/getting-started" + websphere_liberty_operator_sampleapp_image_version = "latest@sha256:d735c2ceae5945a0f20adcbcb04e55472d2520b6d1abb6d3049c8521234d3b7a" # datasource: icr.io/appcafe/open-liberty/samples/getting-started +} + +resource "helm_release" "websphere_liberty_operator_sampleapp" { + depends_on = [kubernetes_namespace.websphere_liberty_sampleapp_namespace[0]] + count = var.install_wslo_sampleapp == true ? 1 : 0 + + name = "websphere-liberty-operator-sampleapp-helm-release" + chart = "${path.module}/chart/${local.websphere_liberty_operator_sampleapp_chart}" + namespace = var.operator_helm_release_namespace + create_namespace = false + timeout = 300 + # dependency_update = true + # force_update = false + force_update = true + cleanup_on_fail = false + wait = true + recreate_pods = true + + disable_openapi_validation = false + + set { + name = "application.image.path" + type = "string" + value = local.websphere_liberty_operator_sampleapp_image_path + } + set { + name = "application.image.version" + type = "string" + value = local.websphere_liberty_operator_sampleapp_image_version + } + + set { + name = "application.name" + type = "string" + value = var.wslo_sampleapp_name + } + + set { + name = "application.namespace" + type = "string" + value = var.wslo_sampleapp_namespace + } + +} + +# waiting for the sample app to start before checking for the URL +resource "time_sleep" "wait_sampleapp" { + depends_on = [helm_release.websphere_liberty_operator_sampleapp[0]] + count = var.install_wslo_sampleapp == true ? 1 : 0 + + create_duration = local.sleep_time_sampleapp_create +} + +data "external" "websphere_liberty_operator_sampleapp_url" { + depends_on = [time_sleep.wait_sampleapp[0]] + program = ["/bin/bash", "${path.module}/scripts/get-sampleapp-url.sh"] + query = { + KUBECONFIG = data.ibm_container_cluster_config.cluster_config.config_file_path + APPNAMESPACE = var.wslo_sampleapp_namespace + APPNAME = var.wslo_sampleapp_name + } +} diff --git a/outputs.tf b/outputs.tf index bb6ea66..8325fa3 100644 --- a/outputs.tf +++ b/outputs.tf @@ -2,7 +2,17 @@ # Outputs ######################################################################################################################## -#output "myoutput" { -# description = "Description of my output" -# value = "value" -#} +output "ws_liberty_operator_namespace" { + description = "Namespace where the WebSphere Liberty operator is installed" + value = var.ws_liberty_operator_namespace +} + +output "ws_liberty_operator_target_namespace" { + description = "Namespace watched by the WebSphere Liberty operator" + value = var.ws_liberty_operator_target_namespace +} + +output "websphere_liberty_operator_sampleapp_url" { + value = data.external.websphere_liberty_operator_sampleapp_url.result.sampleapp_url + description = "WebSphere Liberty sample application URL" +} diff --git a/provider.tf b/provider.tf new file mode 100644 index 0000000..494c945 --- /dev/null +++ b/provider.tf @@ -0,0 +1,20 @@ +############################################################################## +# Config providers +############################################################################## + +provider "ibm" { + ibmcloud_api_key = var.ibmcloud_api_key + region = var.region +} + +provider "helm" { + kubernetes { + host = data.ibm_container_cluster_config.cluster_config.host + token = data.ibm_container_cluster_config.cluster_config.token + } +} + +provider "kubernetes" { + host = data.ibm_container_cluster_config.cluster_config.host + token = data.ibm_container_cluster_config.cluster_config.token +} diff --git a/reference-architecture/was_operator.svg b/reference-architecture/was_operator.svg new file mode 100644 index 0000000..db4fe6a --- /dev/null +++ b/reference-architecture/was_operator.svg @@ -0,0 +1,4 @@ + + + +
IBM Cloud
IBM Cloud
Resource Group
Resource Group
IBM VPC
IBM VPC
OpenShift Cluster
OpenShift Cluster
WebSphere Liberty OperatorWebSphere Application Server
Text is not SVG - cannot display
\ No newline at end of file diff --git a/renovate.json b/renovate.json index 8954b60..4d56818 100644 --- a/renovate.json +++ b/renovate.json @@ -1,4 +1,13 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["github>terraform-ibm-modules/common-dev-assets:commonRenovateConfig"] + "extends": ["github>terraform-ibm-modules/common-dev-assets:commonRenovateConfig"], + "packageRules": [ + { + "description": "Do not allow SLZ version to be updated as we need to lock into version v5.1.1-rc", + "enabled": false, + "matchFileNames": [ + "tests/resources/**" + ] + } + ] } diff --git a/scripts/approve-install-plan.sh b/scripts/approve-install-plan.sh new file mode 100755 index 0000000..21768b0 --- /dev/null +++ b/scripts/approve-install-plan.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +## Subscriptions are set for manual approval. This script approves the first installplan for the initial install + +approve_install_plan(){ + local subscription_name=$1 + local namespace=$2 + local timeout_secs=900 + + echo "Waiting for installplan $subscription_name (${timeout_secs}s timeout)..." + + local install_plan + + # if running on MAC OS use "gtimeout" else run default "timeout" ( + local timeout_cmd=timeout + if [[ $OSTYPE == 'darwin'* ]]; then + # If gtimeout not detected on mac, install coreutils + if ! gtimeout --help &> /dev/null; then + brew install coreutils + fi + timeout_cmd=gtimeout + fi + # shellcheck disable=SC2016 + install_plan="$($timeout_cmd $timeout_secs bash -c 'while [[ "$(kubectl get subscription "'"$subscription_name"'" -n "'"$namespace"'" -o jsonpath="{$.status.installplan.name}")" == "" ]]; do sleep 2; done; echo $(kubectl get subscription "'"$subscription_name"'" -n "'"$namespace"'" -o jsonpath="{$.status.installplan.name}")')" + + if [[ $install_plan != "" ]] + then + echo "Install plan $install_plan found" + echo "Approving install plan $install_plan" + kubectl patch installplan "$install_plan" --type merge --patch "{\"spec\":{\"approved\":true}}" -n "$namespace" + else + echo "Error: Install plan for $subscription_name was not found (namespace: $namespace)" + echo "Grabbing some debug info..." + echo + echo "kubectl get pods -n openshift-marketplace -o wide" + kubectl get pods -n openshift-marketplace -o wide + echo + echo "kubectl get installplan -n $namespace" + kubectl get installplan -n "$namespace" + echo + echo "kubectl get subscription $subscription_name -n $namespace" + kubectl get subscription "$subscription_name" -n "$namespace" + exit 1 + fi + + echo "Waiting for installplan ($subscription_name) to be installed (${timeout_secs}s timeout)..." + kubectl wait --for=condition=Installed --timeout ${timeout_secs}s installplan/"$install_plan" -n "$namespace" +} + +wait_for_operator(){ + local subscription_name=$1 + local namespace=$2 + + echo "Waiting for $subscription_name operator to be running in $namespace (360s timeout)..." + local sm_csv="" + + until [[ $sm_csv != "" ]] + do + echo "Waiting for csv to be created for subscription $subscription_name" + sm_csv=$(kubectl get subscription "$subscription_name" -o jsonpath="{$.status.installedCSV}" -n "$namespace") + sleep 5 + done + + local loop_count=0 + echo "CSV found. Waiting for $subscription_name operator to be running" + until [[ $(kubectl get csv "$sm_csv" -o jsonpath="{$.status.phase}" -n "$namespace") == "Succeeded" || $loop_count -gt 72 ]] + do + echo "Still waiting for $subscription_name operator to be running" + sleep 5 + loop_count=$((loop_count+1)) + done + + if [[ $loop_count -gt 72 ]] + then + echo "Giving up - $subscription_name operator is not running. Check the status of the operator in the $namespace namespace." + exit 1 + fi + + echo "Complete: $subscription_name operator is running" +} + +### Main ### + +namespace=$1 + +## Wait for, and approve install plan for ibm-websphere-liberty +approve_install_plan "ibm-websphere-liberty" "$namespace" + +subscription_names=( "ibm-websphere-liberty" ) +## Post install waits +for subscription_name in "${subscription_names[@]}" +do + wait_for_operator "$subscription_name" "$namespace" +done + +echo "IBM WebSphere Liberty Operator: Install complete" diff --git a/scripts/confirm-wsloperator-operational.sh b/scripts/confirm-wsloperator-operational.sh new file mode 100755 index 0000000..ab3ab25 --- /dev/null +++ b/scripts/confirm-wsloperator-operational.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +set -e + +namespace=$1 +fail=false + +# This script is designed to verify that WebSphere Liberty operator is fully deployed through its deployment resource wlo-controller-manager + +WSLO_DEPLOYMENT_NAME="wlo-controller-manager" + +# sleep 60 seconds initially to provide time for each deployment to get created +sleep 60 + +# Get list of deployments in control plane namespace +DEPLOYMENTS=() +while IFS='' read -r line; do DEPLOYMENTS+=("$line"); done < <(kubectl get deployment "${WSLO_DEPLOYMENT_NAME}" -n "${namespace}" --no-headers | cut -f1 -d ' ') + +# Wait for all deployments to come up - timeout after 5 mins +for dep in "${DEPLOYMENTS[@]}"; do + if ! kubectl rollout status deployment "$dep" -n "${namespace}" --timeout 5m; then + fail=true + fi +done + +# Fail with some debug prints if issues detected +if [ ${fail} == true ]; then + echo "Problem detected. Printing some debug info.." + set +e + echo "Describe output of ibm-operator-catalog CatalogSource in openshift-marketplace namespace" + kubectl describe CatalogSource ibm-operator-catalog -n openshift-marketplace + echo + echo "Describe output of ibm-websphere-liberty Subscription in ${namespace} namespace" + kubectl describe Subscription ibm-websphere-liberty -n "${namespace}" -o wide + echo + echo "List of ${WSLO_DEPLOYMENT_NAME} deployments in ${namespace} namespace" + kubectl get deployment "${WSLO_DEPLOYMENT_NAME}" -n "${namespace}" -o wide + echo + echo "List of pods for ${WSLO_DEPLOYMENT_NAME} deployment in ${namespace} namespace" + kubectl get pods -n "${namespace}" -o wide + WSLOPODS=$(kubectl get pods -n "${namespace}" --no-headers | cut -f1 -d ' ' | grep "${WSLO_DEPLOYMENT_NAME}") + echo + echo "Describe output of ${WSLO_DEPLOYMENT_NAME} deployment pods in ${namespace} namespace" + for pod in "${WSLOPODS[@]}"; do + kubectl describe pod "${pod}" -n "${namespace}" + done + exit 1 +fi diff --git a/scripts/get-sampleapp-url.sh b/scripts/get-sampleapp-url.sh new file mode 100644 index 0000000..b0b5be3 --- /dev/null +++ b/scripts/get-sampleapp-url.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +set -eE + +KUBECONFIG="" +DEBUGFILE="/tmp/getsampleappurl.log" +if [[ -e "${DEBUGFILE}" ]]; then + rm -f "${DEBUGFILE}" +fi + +# jq reads from stdin +function parse_input() { + eval "$(jq -r '@sh "export KUBECONFIG=\(.KUBECONFIG) APPNAMESPACE=\(.APPNAMESPACE) APPNAME=\(.APPNAME)"')" +} + +parse_input + +if [[ -z "${KUBECONFIG}" ]] || [[ -z "${APPNAMESPACE}" ]] || [[ -z "${APPNAME}" ]]; then + echo "[ERROR] one or more input parameter is empty" >> "${DEBUGFILE}" + echo "[ERROR] one or more input parameter is empty" >&2 + SAMPLEAPPROUTE="ERROR" +else + # shellcheck disable=SC2129 + echo "[INFO] using KUBECONFIG ${KUBECONFIG}" >> "${DEBUGFILE}" + # shellcheck disable=SC2129 + echo "[INFO] using APPNAMESPACE ${APPNAMESPACE}" >> "${DEBUGFILE}" + # shellcheck disable=SC2129 + echo "[INFO] using APPNAME ${APPNAME}" >> "${DEBUGFILE}" + + SAMPLEAPPROUTE="$(oc get routes "${APPNAME}" -n "${APPNAMESPACE}" --no-headers | awk '{print $2}')" + + if [[ -z "${SAMPLEAPPROUTE}" ]]; then + echo "[ERROR] Error retrieving sample app url from ${APPNAMESPACE}" >> "${DEBUGFILE}" + SAMPLEAPPROUTE="NOTFOUND" + fi +fi + +echo -n '{"sampleapp_url":"'"${SAMPLEAPPROUTE}"'"}' diff --git a/tests/other_test.go b/tests/other_test.go index d03784f..b2cc9c2 100644 --- a/tests/other_test.go +++ b/tests/other_test.go @@ -2,15 +2,16 @@ package test import ( + "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testhelper" "testing" "github.com/stretchr/testify/assert" ) -func TestRunBasicExample(t *testing.T) { +func TestRunCompleteExample(t *testing.T) { t.Parallel() - options := setupOptions(t, "mod-template-basic", "examples/basic") + options := setupOptions(t, "wslo", completeExampleDir) output, err := options.RunTestConsistency() assert.Nil(t, err, "This should not have errored") diff --git a/tests/pr_test.go b/tests/pr_test.go index 896d726..55f2d75 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -2,9 +2,18 @@ package test import ( + "fmt" + "github.com/stretchr/testify/require" + "os" + "strings" "testing" + "github.com/gruntwork-io/terratest/modules/files" + "github.com/gruntwork-io/terratest/modules/logger" + "github.com/gruntwork-io/terratest/modules/random" + "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" + "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/common" "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testhelper" ) @@ -12,34 +21,96 @@ import ( const resourceGroup = "geretain-test-resources" const completeExampleDir = "examples/complete" -func setupOptions(t *testing.T, prefix string, dir string) *testhelper.TestOptions { +func setupOptions(t *testing.T, prefix string, exampleDir string) *testhelper.TestOptions { options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{ Testing: t, - TerraformDir: dir, + TerraformDir: exampleDir, Prefix: prefix, ResourceGroup: resourceGroup, }) return options } -func TestRunCompleteExample(t *testing.T) { +func TestRunUpgradeExample(t *testing.T) { t.Parallel() - options := setupOptions(t, "mod-template", completeExampleDir) + options := setupOptions(t, "wslo-upg", completeExampleDir) - output, err := options.RunTestConsistency() - assert.Nil(t, err, "This should not have errored") - assert.NotNil(t, output, "Expected some output") + output, err := options.RunTestUpgrade() + if !options.UpgradeTestSkipped { + assert.Nil(t, err, "This should not have errored") + assert.NotNil(t, output, "Expected some output") + } } -func TestRunUpgradeExample(t *testing.T) { +func TestRunSLZExample(t *testing.T) { t.Parallel() - options := setupOptions(t, "mod-template-upg", completeExampleDir) + // ------------------------------------------------------------------------------------ + // Deploy SLZ ROKS Cluster first since it is needed for the WAS extension input + // ------------------------------------------------------------------------------------ - output, err := options.RunTestUpgrade() - if !options.UpgradeTestSkipped { + prefix := fmt.Sprintf("was-%s", strings.ToLower(random.UniqueId())) + realTerraformDir := "./resources" + tempTerraformDir, _ := files.CopyTerraformFolderToTemp(realTerraformDir, fmt.Sprintf(prefix+"-%s", strings.ToLower(random.UniqueId()))) + tags := common.GetTagsFromTravis() + + // Verify ibmcloud_api_key variable is set + checkVariable := "TF_VAR_ibmcloud_api_key" + val, present := os.LookupEnv(checkVariable) + require.True(t, present, checkVariable+" environment variable not set") + require.NotEqual(t, "", val, checkVariable+" environment variable is empty") + + // Programmatically determine region to use based on availability + region, _ := testhelper.GetBestVpcRegion(val, "../common-dev-assets/common-go-assets/cloudinfo-region-vpc-gen2-prefs.yaml", "eu-de") + + logger.Log(t, "Tempdir: ", tempTerraformDir) + existingTerraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: tempTerraformDir, + Vars: map[string]interface{}{ + "prefix": prefix, + "region": region, + "resource_tags": tags, + }, + // Set Upgrade to true to ensure latest version of providers and modules are used by terratest. + // This is the same as setting the -upgrade=true flag with terraform. + Upgrade: true, + }) + + terraform.WorkspaceSelectOrNew(t, existingTerraformOptions, prefix) + _, existErr := terraform.InitAndApplyE(t, existingTerraformOptions) + if existErr != nil { + assert.True(t, existErr == nil, "Init and Apply of temp existing resource failed") + } else { + // ------------------------------------------------------------------------------------ + // Deploy WAS extension + // ------------------------------------------------------------------------------------ + + options := testhelper.TestOptionsDefault(&testhelper.TestOptions{ + Testing: t, + TerraformDir: "extensions/landing-zone", + // Do not hard fail the test if the implicit destroy steps fail to allow a full destroy of resource to occur + ImplicitRequired: false, + TerraformVars: map[string]interface{}{ + "cluster_id": terraform.Output(t, existingTerraformOptions, "management_cluster_id"), + "region": terraform.Output(t, existingTerraformOptions, "region"), + }, + }) + + output, err := options.RunTestConsistency() assert.Nil(t, err, "This should not have errored") assert.NotNil(t, output, "Expected some output") } + + // Check if "DO_NOT_DESTROY_ON_FAILURE" is set + envVal, _ := os.LookupEnv("DO_NOT_DESTROY_ON_FAILURE") + // Destroy the temporary existing resources if required + if t.Failed() && strings.ToLower(envVal) == "true" { + fmt.Println("Terratest failed. Debug the test and delete resources manually.") + } else { + logger.Log(t, "START: Destroy (existing resources)") + terraform.Destroy(t, existingTerraformOptions) + terraform.WorkspaceDelete(t, existingTerraformOptions, prefix) + logger.Log(t, "END: Destroy (existing resources)") + } } diff --git a/tests/resources/README.md b/tests/resources/README.md new file mode 100644 index 0000000..b4c8811 --- /dev/null +++ b/tests/resources/README.md @@ -0,0 +1 @@ +The terraform code in this directory is used by the tests to provision a landing zone ROKS cluster which is required by the WAS SLZ extension. diff --git a/tests/resources/main.tf b/tests/resources/main.tf new file mode 100644 index 0000000..b43b7c3 --- /dev/null +++ b/tests/resources/main.tf @@ -0,0 +1,768 @@ +############################################################################## +# SLZ VPC +############################################################################## + +module "landing_zone" { + source = "git::https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone//patterns//roks//module?ref=v5.1.1-rc" + region = var.region + prefix = var.prefix + tags = var.resource_tags + enable_transit_gateway = false + add_atracker_route = false + + override_json_string = <> ${TF_VARS_FILE} + terraform apply -input=false -auto-approve -var-file=${TF_VARS_FILE} || exit 1 + + region_var_name="region" + cluster_id_var_name="cluster_id" + cluster_id_value=$(terraform output -state=terraform.tfstate -raw management_cluster_id) + + echo "Appending '${cluster_id_var_name}' and '${region_var_name}' input variable values to ${JSON_FILE}.." + + cd "${cwd}" + jq -r --arg region_var_name "${region_var_name}" \ + --arg region_var_value "${REGION}" \ + --arg cluster_id_var_name "${cluster_id_var_name}" \ + --arg cluster_id_value "${cluster_id_value}" \ + '. + {($region_var_name): $region_var_value}, ($cluster_id_var_name): $cluster_id_value' "${JSON_FILE}" > tmpfile && mv tmpfile "${JSON_FILE}" || exit 1 + + echo "Pre-validation complete successfully" +) diff --git a/variables.tf b/variables.tf index df60434..89ea465 100644 --- a/variables.tf +++ b/variables.tf @@ -1,9 +1,84 @@ -######################################################################################################################## +############################################################################## # Input Variables -######################################################################################################################## +############################################################################## -#variable "my_variable" { -# type = string -# description = "A description of my variable" -# default = "default_value" -#} +variable "ibmcloud_api_key" { + description = "APIkey that's associated with the account to use" + type = string + sensitive = true + default = null +} + +variable "region" { + description = "Cluster region" + type = string + nullable = false +} + +variable "cluster_id" { + type = string + description = "Id of the target IBM Cloud OpenShift Cluster" + nullable = false +} + +variable "operator_helm_release_namespace" { + type = string + description = "Namespace to deploy the helm releases. Default to liberty-operator-helm-release" + default = "liberty-operator" + nullable = false +} + +variable "add_ibm_operator_catalog" { + type = bool + description = "Flag to configure the IBM Operator Catalog in the cluster before installing the WebSphere Liberty Operator. Default is true" + default = true +} + +variable "create_ws_liberty_operator_namespace" { + type = bool + description = "Flag to create the namespace where to deploy the WebSphere Liberty Operator. Default to false" + default = false +} + +variable "ws_liberty_operator_namespace" { + type = string + description = "Namespace to install the WebSphere Liberty Operator. Default to openshift-operators" + default = "openshift-operators" + nullable = false +} + +variable "ws_liberty_operator_target_namespace" { + type = string + description = "Namespace to be watched by the WebSphere Liberty Operator. Default to null (operator to watch all namespaces)" + default = null +} + +variable "cluster_config_endpoint_type" { + description = "Specify which type of endpoint to use for for cluster config access: 'default', 'private', 'vpe', 'link'. 'default' value will use the default endpoint of the cluster." + type = string + default = "default" + nullable = false # use default if null is passed in + validation { + error_message = "Invalid Endpoint Type! Valid values are 'default', 'private', 'vpe', or 'link'" + condition = contains(["default", "private", "vpe", "link"], var.cluster_config_endpoint_type) + } +} + +variable "install_wslo_sampleapp" { + description = "Flag to deploy the WebSphere Liberty sample application. Default to false" + type = bool + default = false + nullable = false +} + +variable "wslo_sampleapp_name" { + description = "Application name to use for the WebSphere Liberty sample application" + type = string + default = "websphereliberty-app-sample" +} + +variable "wslo_sampleapp_namespace" { + description = "Namespace to deploy the WebSphere Liberty sample application" + type = string + default = "samplelibertyapp" +} diff --git a/version.tf b/version.tf index bcb2505..bfcdb3f 100644 --- a/version.tf +++ b/version.tf @@ -1,12 +1,30 @@ terraform { required_version = ">= 1.3.0, <1.6.0" - # If your module requires any terraform providers, uncomment the "required_providers" section below and add all required providers. - # Each required provider's version should be a flexible range to future proof the module's usage with upcoming minor and patch versions. - - # required_providers { - # ibm = { - # source = "IBM-Cloud/ibm" - # version = ">= 1.49.0, < 2.0.0" - # } - # } + required_providers { + # Use a range in modules + ibm = { + source = "ibm-cloud/ibm" + version = ">= 1.59.0, < 2.0.0" + } + helm = { + source = "hashicorp/helm" + version = ">= 2.8.0, <3.0.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.16.1, <3.0.0" + } + time = { + source = "hashicorp/time" + version = ">= 0.9.1, < 1.0.0" + } + null = { + source = "hashicorp/null" + version = ">= 3.2.1, < 4.0.0" + } + external = { + source = "hashicorp/external" + version = ">=2.2.3, <3.0.0" + } + } }