Skip to content

Commit

Permalink
feat: Migrate to python the script to get sampleapp url and reduced w…
Browse files Browse the repository at this point in the history
…ait time (#31)
  • Loading branch information
vbontempi authored Apr 26, 2024
1 parent c1a1ed3 commit b83f6bb
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 61 deletions.
18 changes: 12 additions & 6 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ locals {
# sleep times definition
sleep_time_catalog_create = "60s"
sleep_time_operator_create = "120s"
sleep_time_sampleapp_create = "60s" # time to wait for the sampleapp route to be defined
sleep_time_sampleapp_create = "30s" # time to wait for the sampleapp route to be defined

# helm chart names
ibm_operator_catalog_chart = "ibm-operator-catalog"
Expand Down Expand Up @@ -260,7 +260,7 @@ resource "helm_release" "websphere_liberty_operator_sampleapp" {

}

# waiting for the sample app to start before checking for the URL
# waiting for the sample app to be deployed before starting to query 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
Expand All @@ -270,10 +270,16 @@ resource "time_sleep" "wait_sampleapp" {

data "external" "websphere_liberty_operator_sampleapp_url" {
depends_on = [time_sleep.wait_sampleapp[0]]
program = ["/bin/bash", "${path.module}/scripts/get-sampleapp-url.sh"]
program = ["python3", "${path.module}/scripts/get-sampleapp-url.py"]
query = {
KUBECONFIG = data.ibm_container_cluster_config.cluster_config.config_file_path
APPNAMESPACE = var.wslo_sampleapp_namespace
APPNAME = var.wslo_sampleapp_name
kubeconfig = data.ibm_container_cluster_config.cluster_config.config_file_path
appnamespace = var.wslo_sampleapp_namespace
appname = var.wslo_sampleapp_name
attempts = 30 # attempts to retrieve the sampleapp url (sleep of 10s between attempts)
}
}

locals {
# getting sampleapp_url in a JSON string in the format {"sampleapp_url": "[THE URL]"}
sampleapp_url_response = jsondecode(data.external.websphere_liberty_operator_sampleapp_url.result.response)
}
2 changes: 1 addition & 1 deletion outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ output "ws_liberty_operator_target_namespace" {
}

output "websphere_liberty_operator_sampleapp_url" {
value = data.external.websphere_liberty_operator_sampleapp_url.result.sampleapp_url
value = local.sampleapp_url_response.sampleapp_url
description = "WebSphere Application Server Liberty sample application URL."
}
156 changes: 156 additions & 0 deletions scripts/get-sampleapp-url.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#!/usr/bin/env python3

#########################################################################################################
# Script to retrieve the websphere sample app url from the openshift routes in the sample app namespace
#########################################################################################################

import json
import logging
import os
import subprocess
import sys
import time

input = sys.stdin.read()
input_json = json.loads(input)

# json response format
json_response = {"response": ""}

# debugging file init
DEBUGFILE = "getsampleappurl.log"
if os.path.exists(DEBUGFILE):
os.remove(DEBUGFILE)

logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[logging.FileHandler(DEBUGFILE)],
)


# method to retrieve json attribute - returns the default value if the key doesn't exist or exists but it is null
def get_attribute(data, attribute, default_value):
return data.get(attribute) or default_value


def returnFatalError(message, mustExit=False):
message = {"error": "Error: " + message, "sampleapp_url": sampleapp_url}
returnResponse(message, True)
if mustExit:
sys.exit(1)


# return the string on the standard error
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)


# formats the string returned as response
# if isError is true the output of the string is returned on sterr instead of stout
def returnResponse(responseObject, isError=False):
json_response_formatted = json.dumps(responseObject, indent=2)
logging.info("returnResponse - response JSON content:")
logging.info(json_response_formatted)
json_response["response"] = json.dumps(responseObject, indent=None)
json_response_string = json.dumps(json_response, indent=None)
if isError:
eprint(json_response_string)
else:
print(json_response_string)


# default values
SLEEP = 10 # seconds to sleep
DEFAULTRETRIES = 30 # 30 x 5 = 30 secs = 5 mins

# reset input variables
KUBECONFIG = ""
APPNAMESPACE = ""
APPNAME = ""
ATTEMPTS = 0

input_json_formatted = json.dumps(input_json, indent=2)

logging.info("input JSON content:")
logging.info(input_json_formatted)

# setting input variables
KUBECONFIG = get_attribute(input_json, "kubeconfig", "")
APPNAMESPACE = get_attribute(input_json, "appnamespace", "")
APPNAME = get_attribute(input_json, "appname", "")
ATTEMPTS = int(get_attribute(input_json, "attempts", 0))

logging.info("Input parameters:")
logging.info(f"KUBECONFIG {KUBECONFIG}")
logging.info(f"APPNAMESPACE: {APPNAMESPACE}")
logging.info(f"APPNAME: {APPNAME}")
logging.info(f"ATTEMPTS: {ATTEMPTS}")

# checking empty values
if not (len(KUBECONFIG.strip()) and len(APPNAMESPACE.strip()) and len(APPNAME.strip())):
message = "One or more mandatory parameter is empty"
logging.error(message)
returnFatalError(message)

if ATTEMPTS == 0:
ATTEMPTS = DEFAULTRETRIES
logging.info(f"Input ATTEMPTS parameter is 0 so using default value {ATTEMPTS}")

# default value for the sample app url
sampleapp_url = "NOTFOUND"
for counter in range(ATTEMPTS):
if counter == (ATTEMPTS - 1):
# if attempts are over limit giving up
logging.error(
f"attempt {counter + 1} reached max amount of retries {ATTEMPTS} - giving up"
)
logging.error(
f"Error retrieving sample app {APPNAME} url in namespace {APPNAMESPACE}"
)
emsg = f"Error retrieving sample app {APPNAME} url in namespace {APPNAMESPACE}"
logging.error(emsg)
returnFatalError(emsg)

# Getting status of sdnlb LB
logging.info(
f"Attempt {counter + 1} / {ATTEMPTS} - Retrieving sample app {APPNAME} url in namespace {APPNAMESPACE}"
)
try:
oc_result = subprocess.run(
["oc", "get", "routes", "-n", APPNAMESPACE, APPNAME, "-o", "json"],
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
encoding="utf-8",
)
logging.debug(oc_result.stdout)
app_routes = json.loads(oc_result.stdout)
logging.info(f"App routes: {app_routes}")
status = app_routes.get("status", "")
if status != "":
logging.info(f"Status: {status}")
ingress = status.get("ingress", "")
if ingress != "":
logging.info(f"Ingress: {ingress}")
route = ingress[0].get("host")
logging.info(f"Route: {route}")
if route != "":
msg = f"Attempt {counter + 1} / {ATTEMPTS} - Found route {route} for sample app {APPNAME} routes in namespace {APPNAMESPACE}"
sampleapp_url = route
logging.info(msg)
break

except subprocess.CalledProcessError:
emsg = f"Attempt {counter + 1} / {ATTEMPTS} - error in getting sample app {APPNAME} routes in namespace {APPNAMESPACE}"
logging.error(emsg)

msg = f"Attempt {counter + 1} / {ATTEMPTS} - route for sample app {APPNAME} routes in namespace {APPNAMESPACE} not found yet"
logging.info(msg)
logging.info(f"Sleeping for {SLEEP} seconds before having a new attempt")
time.sleep(SLEEP)

response = {"sampleapp_url": sampleapp_url}
logging.debug(json.dumps(response, indent=2))

returnResponse(response)
38 changes: 0 additions & 38 deletions scripts/get-sampleapp-url.sh

This file was deleted.

19 changes: 3 additions & 16 deletions tests/pr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,9 @@ func setupOptions(t *testing.T, prefix string, exampleDir string) *testhelper.Te
List: []string{
// to skip update error due to operator sample app updates
"module.websphere_liberty_operator.helm_release.websphere_liberty_operator_sampleapp[0]",
// to be all removed after the merge of https://github.com/terraform-ibm-modules/terraform-ibm-websphere-liberty-operator/pull/12 or corresponding fix https://github.com/terraform-ibm-modules/terraform-ibm-websphere-liberty-operator/pull/36
// manage_all_addons moved to false as default
"module.ocp_base.ibm_container_addons.addons",
},
},

IgnoreDestroys: testhelper.Exemptions{ // Ignore for consistency check
List: []string{
// adding resources to ignore for modules version update - to be all removed after the merge of https://github.com/terraform-ibm-modules/terraform-ibm-websphere-liberty-operator/pull/12 or corresponding fix https://github.com/terraform-ibm-modules/terraform-ibm-websphere-liberty-operator/pull/36
// wait_operators is removed
"module.ocp_base.time_sleep.wait_operators",
// manage_all_addons moved to false as default
"module.ocp_base.ibm_container_addons.addons",
// upgrade of cos module
"module.ocp_base.module.cos_instance[0].time_sleep.wait_for_authorization_policy[0]",
"module.ocp_base.module.cos_instance[0].ibm_resource_key.resource_key[0]",
// to avoid upgrade to fail when sleep time is reduced
// remove this ignore once https://github.com/terraform-ibm-modules/terraform-ibm-websphere-liberty-operator/pull/31 is merged
"module.websphere_liberty_operator.time_sleep.wait_sampleapp[0]",
},
},
})
Expand Down

0 comments on commit b83f6bb

Please sign in to comment.