SREWorks/sbin/export-built-in-app.py

356 lines
13 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
import os.path
import sys
import json
import urllib
import zipfile
from tempfile import NamedTemporaryFile
import shutil
import yaml
import copy
try:
import urllib.request
except ImportError:
pass
self_path = os.path.split(os.path.realpath(__file__))[0]
VALUES_MAP = {
"appParameterValues":{
"REDIS_HOST": '{{ env.APPMANAGER_REDIS_HOST }}',
"REDIS_PORT": '{{ env.APPMANAGER_REDIS_PORT }}',
"REDIS_PASSWORD": '{{ env.APPMANAGER_REDIS_PASSWORD }}',
"ES_ENDPOINT": 'http://${DATA_ES_HOST}:${DATA_ES_PORT}',
"ES_USERNAME": '${DATA_ES_USER}',
"ES_PASSWORD": '${DATA_ES_PASSWORD}',
"DATA_DB_HOST": '${DATAOPS_DB_HOST}',
"DATA_DB_PORT": '${DATAOPS_DB_PORT}',
"DATA_DB_USER": '${DATAOPS_DB_USER}',
"DATA_DB_PASSWORD": '${DATAOPS_DB_PASSWORD}',
"KAFKA_ENDPOINT": '${KAFKA_ENDPOINT}:9092',
"ELASTICSEARCH_HOST": '${DATA_ES_HOST}',
"ELASTICSEARCH_PORT": '${DATA_ES_PORT}',
"ELASTICSEARCH_USER": '${DATA_ES_USER}',
"ELASTICSEARCH_PASSWORD": '${DATA_ES_PASSWORD}',
"DATA_ES_HOST": '${DATA_ES_HOST}',
"DATA_ES_PORT": '${DATA_ES_PORT}',
"DATA_ES_USER": '${DATA_ES_USER}',
"DATA_ES_PASSWORD": '${DATA_ES_PASSWORD}',
"NAMESPACE_ID": '${NAMESPACE_ID}',
"CLUSTER_ID": "master",
"STAGE_ID": "prod",
"APPMANAGER_USERNAME": "${APPMANAGER_USERNAME}",
"APPMANAGER_PASSWORD": "${APPMANAGER_PASSWORD}",
"APPMANAGER_CLIENT_ID": "${APPMANAGER_CLIENT_ID}",
"APPMANAGER_CLIENT_SECRET": "${APPMANAGER_CLIENT_SECRET}",
},
"componentParameterValues":{
}
}
def values_tpl_replace(launchYAML, patchYAML):
launchYAML['metadata']['annotations']['namespaceId'] = '${NAMESPACE_ID}'
launchYAML['metadata']['annotations']['clusterId'] = 'master'
launchYAML['metadata']['annotations']['stageId'] = 'prod'
for appValue in launchYAML["spec"]["parameterValues"]:
if appValue["name"] in VALUES_MAP["appParameterValues"]:
appValue["value"] = VALUES_MAP["appParameterValues"][appValue["name"]]
patchComponents = {}
if patchYAML != None:
for component in patchYAML.get("components", []):
component["parameterValueMaps"] = {}
for v in component.get("parameterValues", []):
component["parameterValueMaps"][v["name"]] = v["value"]
patchComponents[component["revisionName"]] = component
for component in launchYAML["spec"]["components"]:
newParameterValues = []
for delKey in ["clusterId","namespaceId","stageId"]:
if delKey in component:
del component[delKey]
for value in component.get("parameterValues", []):
# 如果该变量在app级别存在则使用app级别的且component级别不展示变量
valueName = value["name"].replace("Global.",'')
if valueName in VALUES_MAP["appParameterValues"]:
launchYAML["spec"]["parameterValues"].append({"name": valueName, "value": VALUES_MAP["appParameterValues"][valueName]})
else:
newParameterValues.append(value)
component["parameterValues"] = newParameterValues
component["scopes"] = [{
"scopeRef": {
"apiVersion": "apps.abm.io/v1",
"kind": "Cluster",
"name": "{{ Global.CLUSTER_ID }}",
}},{
"scopeRef": {
"apiVersion": "apps.abm.io/v1",
"kind": "Namespace",
"name": "{{ Global.NAMESPACE_ID }}",
}},{
"scopeRef": {
"apiVersion": "apps.abm.io/v1",
"kind": "Stage",
"name": "{{ Global.STAGE_ID }}",
}}]
if component["revisionName"].startswith("INTERNAL_ADDON"):
component["parameterValues"].append({
"name": "STAGE_ID",
"value": "prod",
"toFieldPaths": ["spec.stageId"]
})
if component["revisionName"] == "INTERNAL_ADDON|appmeta|_":
component["parameterValues"].append({
"name": "OVERWRITE_IS_DEVELOPMENT",
"value": "true",
"toFieldPaths": ["spec.overwriteIsDevelopment"]
})
if patchComponents.get(component["revisionName"]) != None:
patchValues = patchComponents[component["revisionName"]]["parameterValueMaps"]
for v in component["parameterValues"]:
if patchValues.get(v["name"]) != None:
v["value"] = patchValues[v["name"]]
del patchValues[v["name"]]
# 如果变量不存在也要append进去
if len(patchValues) > 0:
for k,v in patchValues.items():
component["parameterValues"].append({
"name": k,
"value": v,
})
if patchComponents[component["revisionName"]].get("traits") != None:
if "traits" not in component: component["traits"] = []
component["traits"] += patchComponents[component["revisionName"]]["traits"]
def only_dup_filter(launchYAML, patchYAML):
patchComponents = {}
for c in patchYAML["components"]:
patchComponents[c["revisionName"]] = c
for component in launchYAML["spec"]["components"]:
if patchComponents.get(component["revisionName"]) != None:
patchTraits = patchComponents[component["revisionName"]].get("traits",[])
if "traits" not in component:
component["traits"] = []
traits = {}
for trait in component["traits"]:
traits[trait["name"]] = trait
for trait in patchTraits:
traits[trait["name"]] = trait
component["traits"] = list(filter(lambda t: t.get("spec") is not None, list(traits.values())))
def only_frontend_filter(launchYAML):
newComponents = []
gatewayTrait = {}
for component in launchYAML["spec"]["components"]:
if component["revisionName"].startswith("INTERNAL_ADDON"):
newComponents.append(component)
elif component["revisionName"].startswith("HELM"):
newComponents.append(component)
launchYAML["spec"]["components"] = newComponents
def only_frontend_dev_filter(launchYAML):
newComponents = []
gatewayTrait = {}
for component in launchYAML["spec"]["components"]:
if component["revisionName"].startswith("INTERNAL_ADDON"):
newComponents.append(component)
launchYAML["spec"]["components"] = newComponents
def only_backend_filter(launchYAML):
newComponents = []
gatewayTrait = {}
for component in launchYAML["spec"]["components"]:
if not component["revisionName"].startswith("INTERNAL_ADDON") and not component["revisionName"].startswith("HELM"):
newComponents.append(component)
if {"component": "RESOURCE_ADDON|system-env@system-env"} in component.get("dependencies",[]):
component["dependencies"].remove({"component": "RESOURCE_ADDON|system-env@system-env"})
launchYAML["spec"]["components"] = newComponents
def frontend_dev_replace(launchYAML, devYAML):
launchYAML['metadata']['annotations']['stageId'] = 'dev'
for appValue in launchYAML["spec"]["parameterValues"]:
if appValue["name"] == "STAGE_ID":
appValue["value"] = "dev"
for component in launchYAML["spec"]["components"]:
for compValue in component["parameterValues"]:
if compValue["name"] == "STAGE_ID":
compValue["value"] = "dev"
if devYAML != None:
for devComp in devYAML["components"]:
if devComp["revisionName"] == component["revisionName"]:
if "traits" not in component: component["traits"] = []
component["traits"] += devComp["traits"]
def download(url):
if hasattr(urllib, "urlretrieve"):
f = NamedTemporaryFile(delete=False)
return urllib.urlretrieve(url, f.name)[0]
else:
return urllib.request.urlretrieve(url)[0]
f = open(self_path + '/../built-in.json', 'r')
builtInList = json.loads(f.read())
f.close()
# 获取云端市场的索引文件sw-index.json
if len(sys.argv) > 1:
endpoint = sys.argv[1]
else:
endpoint = "http://sreworks.oss-cn-beijing.aliyuncs.com/markets"
f = open(download(endpoint + "/sw-index.json"), 'r')
markets = json.loads(f.read())
f.close()
marketPacks = {}
for marketPack in markets["packages"]:
marketPacks[marketPack["appId"]] = marketPack
for buildIn in builtInList:
print(buildIn)
if buildIn.get("patch") != None:
f = open(self_path + "/../" + buildIn["patch"], 'r')
patchYAML = yaml.safe_load(f.read())
print(patchYAML)
f.close()
else:
patchYAML = {}
marketPack = marketPacks[buildIn["appId"]]
lastVersion = marketPack["packageVersions"][-1]
if marketPack["urls"][lastVersion].startswith("http"):
lastPackageUrl = marketPack["urls"][lastVersion]
else:
lastPackageUrl = endpoint + "/" + urllib.parse.quote(marketPack["urls"][lastVersion])
loalPath = self_path + "/../" + buildIn["packagePath"]
if os.path.exists(loalPath):
shutil.rmtree(loalPath)
else:
os.makedirs(loalPath)
print(buildIn["appId"] + " -> " + loalPath)
with zipfile.ZipFile(download(lastPackageUrl),"r") as zip_ref:
zip_ref.extractall(loalPath)
# 根据meta.yaml生成 launch-example.yaml
f = open(loalPath + '/meta.yaml', 'r')
metaInfo = yaml.safe_load(f.read())
f.close()
launchYAML = {
"apiVersion": "core.oam.dev/v1alpha2",
"kind": "ApplicationConfiguration",
"metadata": {
"annotations": {
"appId": buildIn["appId"],
},
"name": buildIn["appId"],
},
"spec":{
"parameterValues": [{
"name": "CLUSTER_ID",
"value": "",
},{
"name": "NAMESPACE_ID",
"value": "",
},{
"name": "STAGE_ID",
"value": "",
},{
"name": "APP_ID",
"value": buildIn["appId"],
}],
"components": [],
"policies": [],
"workflow":{
"steps": []
}
}
}
for component in metaInfo["componentPackages"]:
packageOptions = json.loads(component["packageOptions"])
if "componentConfiguration" in packageOptions:
launchYAML["spec"]["components"].append(yaml.safe_load(packageOptions["componentConfiguration"]))
else:
launchYAML["spec"]["components"].append({
"revisionName": component["componentType"] + "|" + component["componentName"] + "|_"
})
f = open(loalPath + '/launch-example.yaml', 'w')
f.write(yaml.safe_dump(launchYAML, width=float("inf")))
f.close()
values_tpl_replace(launchYAML, patchYAML.get("launch.yaml.tpl"))
f = open(loalPath + '/launch.yaml.tpl', 'w')
f.write(yaml.safe_dump(launchYAML, width=float("inf")))
f.close()
for d in buildIn.get("duplicateYAML",[]):
if d.get("source") == "launch.yaml.tpl":
dupYAML = copy.deepcopy(launchYAML)
if patchYAML.get(d["target"]) != None:
only_dup_filter(dupYAML, patchYAML.get(d["target"]))
f = open(loalPath + '/' + d["target"], 'w')
f.write(yaml.safe_dump(dupYAML, width=float("inf")))
f.close()
backendLaunchYAML = json.loads(json.dumps(launchYAML))
only_backend_filter(backendLaunchYAML)
if len(backendLaunchYAML["spec"]["components"]) > 0:
f = open(loalPath + '/launch-backend.yaml.tpl', 'w')
f.write(yaml.safe_dump(backendLaunchYAML, width=float("inf")))
f.close()
only_frontend_filter(launchYAML)
f = open(loalPath + '/launch-frontend.yaml.tpl', 'w')
f.write(yaml.safe_dump(launchYAML, width=float("inf")))
f.close()
only_frontend_dev_filter(launchYAML)
frontend_dev_replace(launchYAML, patchYAML.get("launch-frontend-dev.yaml.tpl"))
f = open(loalPath + '/launch-frontend-dev.yaml.tpl', 'w')
f.write(yaml.safe_dump(launchYAML, width=float("inf")))
f.close()
for name in os.listdir(loalPath):
filename = loalPath + "/" + name
if zipfile.is_zipfile(filename):
dirName = filename + ".dir"
os.makedirs(dirName)
with zipfile.ZipFile(filename,"r") as zip_ref:
zip_ref.extractall(dirName)
os.remove(filename)