nuvolaris/whisk_actions_deployer.py (153 lines of code) (raw):
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
# wsk project deploy --project deploy/whisk-system —-apihost http://localhost:3233 --auth 789c46b1-71f6-4ed5-8c54-816aa4f8c502:abczO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP
#
import logging
import json
import nuvolaris.config as cfg
import nuvolaris.template as ntp
import nuvolaris.util as util
import nuvolaris.kustomize as kust
import os
from nuvolaris.whisk_system_util import WhiskSystemClient
from nuvolaris.util import nuv_retry
from subprocess import CompletedProcess
def get_couchdb_inputs():
couchdb_host = cfg.get("couchdb.host") or "couchdb"
couchdb_port = cfg.get("couchdb.port") or "5984"
cdb_inputs=[]
cdb_inputs.append({"key":"couchdb_user", "value":cfg.get("couchdb.admin.user", "COUCHDB_ADMIN_USER", "whisk_admin")})
cdb_inputs.append({"key":"couchdb_password", "value":cfg.get("couchdb.admin.password", "COUCHDB_ADMIN_PASSWORD", "some_passw0rd")})
cdb_inputs.append({"key":"couchdb_host", "value":couchdb_host})
cdb_inputs.append({"key":"couchdb_port", "value":couchdb_port})
return cdb_inputs
def prepare_login_action():
login = {
"name":"login",
"function":"login.zip",
"runtime":"python:3",
"web":"true",
"inputs":get_couchdb_inputs()
}
return login
def prepare_secrets_action():
secrets = {
"name":"secrets",
"function":"secrets.zip",
"runtime":"python:3",
"web":"true",
"inputs":get_couchdb_inputs()
}
return secrets
def prepare_content_action():
minio_host= cfg.get("minio.host") or "nuvolaris-minio"
minio_port= cfg.get("minio.port") or "9000"
minio_full_host = f"{minio_host}.nuvolaris.svc.cluster.local"
content_inputs=[]
content_inputs.append({"key":"minio_host", "value":minio_full_host})
content_inputs.append({"key":"minio_port", "value":minio_port})
content = {
"name":"content",
"function":"content.zip",
"runtime":"python:3",
"web":"true",
"inputs":content_inputs
}
return content
def prepare_redis_action():
redis = {
"name":"redis",
"function":"redis.zip",
"runtime":"python:3",
"web":"raw",
"inputs":get_couchdb_inputs()
}
return redis
def prepare_psql_action():
psql = {
"name":"psql",
"function":"psql.zip",
"runtime":"python:3",
"web":"raw",
"inputs":get_couchdb_inputs()
}
return psql
def prepare_minio_action():
minio = {
"name":"minio",
"function":"minio.zip",
"runtime":"python:3",
"web":"raw",
"inputs":get_couchdb_inputs()
}
return minio
def prepare_dev_upload_action():
dev_upload = {
"name":"devel_upload",
"function":"devel_upload.zip",
"runtime":"python:3",
"web":"raw",
"inputs":get_couchdb_inputs()
}
return dev_upload
def prepare_ferretdb_action():
ferretdb = {
"name":"ferretdb",
"function":"ferretdb.zip",
"runtime":"python:3",
"web":"raw",
"inputs":get_couchdb_inputs()
}
return ferretdb
def prepare_dev_download_action():
dev_download = {
"name":"devel_download",
"function":"devel_download.zip",
"runtime":"python:3",
"web":"raw",
"inputs":get_couchdb_inputs()
}
return dev_download
def prepare_system_actions():
""" Builds a suitable structure to generate a deployment manifest using a template
"""
actions = []
actions.append(prepare_login_action())
actions.append(prepare_secrets_action())
actions.append(prepare_content_action())
actions.append(prepare_redis_action())
actions.append(prepare_psql_action())
actions.append(prepare_minio_action())
actions.append(prepare_dev_upload_action())
actions.append(prepare_ferretdb_action())
actions.append(prepare_dev_download_action())
return {"actions":actions}
def process_wsk_result(result: CompletedProcess, expected_success_msg: str):
"""
Parses a subprocess.CompletedProcess object and raises an exception if the
returncode != 0 or the stdout response does not contains the expected message.
Raising an Exception forces a retry if the @nuv_retry decorator is used.
"""
has_error = False
logging.debug(f"expected message for success {expected_success_msg}")
returncode = result.returncode
output = result.stdout.decode()
error = result.stderr.decode()
if returncode != 0:
logging.warn(f"error {error} detected when deploying system action")
has_error = True
if not expected_success_msg in output:
logging.warn(f"response {output} does not contains the expected result {expected_success_msg}")
has_error = True
if has_error:
logging.warn(f"could not validate wsk response {result}")
raise Exception("whisk system action deployement failure. Forcing a retry")
logging.info(f"successfully validated wsk response {result}")
@nuv_retry()
def safe_deploy(wskClient):
logging.info("*** deploying deploy/whisk-system project")
deployProjectResponse = wskClient.wsk("project","deploy","--project","deploy/whisk-system")
process_wsk_result(deployProjectResponse, "Success")
actionListResult = wskClient.wsk("action","list")
process_wsk_result(actionListResult, "whisk-system/nuv/login")
return True
def deploy_whisk_system_action():
try:
auth = cfg.get('openwhisk.namespaces.whisk-system')
data = prepare_system_actions()
tplres = kust.processTemplate("whisk-system","whisk-system-manifest-tpl.yaml",data,"manifest.yaml")
wskClient = WhiskSystemClient(auth)
result = safe_deploy(wskClient)
return result
except Exception as e:
logging.error("Error detected when deploying system actions", e)
return False