02.29 SCF VSCode遷移過渡到Serverless Framework

SCFCLI和VSCode的插件很早之前就有了,也有很多用戶在使用這兩個工具, 使用它們可以通過已經寫的Yaml直接把函數部署到線上,非常方便。但是眼尖的小夥伴已經發現這樣一件事:SCFCLI和VSCode插件貌似很久都沒更新了,而且雲函數的小夥伴在極力推動大家使用Serverless Framework。可以看到SCFCLI在6月份的時候更新頻繁,而現在,更新緩慢。

同時,細心的小夥伴還發現了,Serverless Framework貌似比SCFCLI好用啊!因為它不僅僅可以部署函數,還可以部署APIGW,COS,CDN……最主要,通過Serverless Frameworek還可以快速的把常用的框架,例如Express、Flask、Django…..等直接部署到雲函數上,這是多方便的一件事情啊!

就問還在用SCFCLI的小夥伴,你們酸沒酸?

有的小夥伴在躍躍欲試之後,終於下定決心,將SCFCLI放棄掉,開始使用Serverless Framework,那麼問題來了,這兩個東西的Yaml寫的不一樣,是完全不一樣,那麼應該如何把已有的SCFCLI/VSCode插件的Yaml快速轉換成為Serverless Framework的Yaml呢?

下面就是幾個簡單的實現方法:

通過網頁進行轉換

作為社區愛好者,我必然要提供一個簡單的網頁,來做這個事情:

http://serverless.0duzhan.com/app/scf_2_serverless/

通過這個網址,你只需要輸入基於SCFCLI的Yaml,就可以快速轉換:

從SCFCLI/SCF VSCode遷移過渡到Serverless Framework

轉換結果是可以同時生成Component的Yaml和Plugin的Yaml

通過接口自主轉換

接口地址:

  • Component:http://service-8d3fi753-1256773370.bj.apigw.tencentcs.com/release/scf_2_serverless/components/
  • Plugin:http://service-8d3fi753-1256773370.bj.apigw.tencentcs.com/release/scf_2_serverless/plugin/

輸入參數:yaml,字符串類型,就是之前SCFCLI/VSCODE插件的Yaml內容

輸出參數:error,布爾類型,是否出錯;result,字符串類型,結果(error為true,此處輸出錯誤信息,為false時輸出新的yaml結果)

以Python語言為例,將原有的Yaml轉換成為Component的Yaml可以這樣操作:

<code>import urllib.requestimport jsonwith open("template.yaml", 'r') as f:    yamlData = f.read()url = "http://service-8d3fi753-1256773370.bj.apigw.tencentcs.com/release/scf_2_serverless/components/"data = {    "yaml": yamlData}yamlResult = json.loads(urllib.request.urlopen(urllib.request.Request(url=url, data=json.dumps(data).encode("utf-8"))).read().decode("utf-8"))print(yamlResult)with open("output.yaml", "w") as f:    f.write(yamlResult['result'])/<code>

這樣就可以把已有的SCFCLI Yaml轉換成Serverless Component的Yaml了,Plugin的轉換方法同理,只需要更換一個一下url地址就好了。

自己寫本地腳本來轉

<code>def getBaseFunctionComponents(functionInformation, functionName=None, tempInputs=None):    tempInputs = tempInputs if tempInputs else {}    if functionName:        tempInputs["name"] = functionName    if isinstance(functionInformation, dict):        for eveFunctionKey, eveFunctionValue in functionInformation.items():            if eveFunctionKey not in ["Events", "Environment", "VpcConfig", "Type", "Role"]:                tempKey = str.lower(eveFunctionKey[0]) + eveFunctionKey[1:]                tempInputs[tempKey] = eveFunctionValue            else:                if eveFunctionKey == "Environment":                    if eveFunctionValue and "Variables" in eveFunctionValue:                        tempEnvironment = {                            "variables": eveFunctionValue["Variables"]                        }                        tempInputs["environment"] = tempEnvironment                elif eveFunctionKey == "VpcConfig":                    tempVpcConfig = {}                    if eveFunctionValue and "SubnetId" in eveFunctionValue:                        tempSubnetId = eveFunctionValue["SubnetId"]                        tempVpcConfig["subnetId"] = tempSubnetId                    if eveFunctionValue and "VpcId" in eveFunctionValue:                        tempVpcId = eveFunctionValue["VpcId"]                        tempVpcConfig["vpcId"] = tempVpcId                    tempInputs["vpcConfig"] = tempVpcConfig                elif eveFunctionKey == "Events":                    tempEvents = []                    if isinstance(eveFunctionValue, dict):                        for eveEventKey, eveEventValue in eveFunctionValue.items():                            if isinstance(eveEventValue["Properties"], dict):                                tempEvent = {}                                if eveEventValue["Type"] == "APIGW":                                    tempEvent['apigw'] = {                                        "name": eveEventKey,                                        "parameters": {}                                    }                                    tempParameter = {}                                    tempEndpoints = {"path": "/" + functionName}                                    for eveParameterKey, eveParameterValue in eveEventValue["Properties"].items():                                        if eveParameterKey == "StageName":                                            tempParameter["environment"] = eveParameterValue                                        elif eveParameterKey == "ServiceId" and eveParameterValue:                                            tempParameter["serviceId"] = eveParameterValue                                        elif eveParameterKey == "HttpMethod":                                            tempEndpoints["method"] = eveParameterValue                                        elif eveParameterKey == "IntegratedResponse":                                            tempEndpoints["function"] = {"isIntegratedResponse": eveParameterValue}                                    tempParameter["endpoints"] = [tempEndpoints, ]                                    tempEvent['apigw']["parameters"] = tempParameter                                elif eveEventValue["Type"] == "COS":                                    tempEvent['cos'] = {                                        "name": eveEventKey,                                        "parameters": {}                                    }                                    tempParameter = {}                                    for eveParameterKey, eveParameterValue in eveEventValue["Properties"].items():                                        if eveParameterKey == "Filter":                                            tempFilter = {}                                            for eveFilterKey, eveFilterValue in eveParameterValue.items():                                                tempKey = str.lower(eveFilterKey[0]) + eveFilterKey[1:]                                                tempFilter[tempKey] = eveFilterValue                                            tempParameter["filter"] = tempFilter                                        else:                                            tempKey = str.lower(eveParameterKey[0]) + eveParameterKey[1:]                                            tempParameter[tempKey] = eveParameterValue                                    tempEvent['cos']["parameters"] = tempParameter                                elif eveEventValue["Type"] == "Timer":                                    tempEvent['timer'] = {                                        "name": eveEventKey,                                        "parameters": {}                                    }                                    tempParameter = {}                                    for eveParameterKey, eveParameterValue in eveEventValue["Properties"].items():                                        tempKey = str.lower(eveParameterKey[0]) + eveParameterKey[1:]                                        tempParameter[tempKey] = eveParameterValue                                    tempEvent['timer']["parameters"] = tempParameter                                elif eveEventValue["Type"] == "CMQ":                                    tempEvent['cmq'] = {                                        "name": eveEventKey,                                        "parameters": {}                                    }                                    tempParameter = {}                                    for eveParameterKey, eveParameterValue in eveEventValue["Properties"].items():                                        tempKey = str.lower(eveParameterKey[0]) + eveParameterKey[1:]                                        tempParameter[tempKey] = eveParameterValue                                    tempEvent['cmq']["parameters"] = tempParameter                                elif eveEventValue["Type"] == "CKafka":                                    tempEvent['ckafka'] = {                                        "name": eveEventKey,                                        "parameters": {}                                    }                                    tempParameter = {}                                    for eveParameterKey, eveParameterValue in eveEventValue["Properties"].items():                                        tempKey = str.lower(eveParameterKey[0]) + eveParameterKey[1:]                                        tempParameter[tempKey] = eveParameterValue                                    tempEvent['ckafka']["parameters"] = tempParameter                                tempEvents.append(tempEvent)                    if tempEvents:                        tempInputs["events"] = tempEvents    return tempInputsdef getFunctionComponents(functionName, function, tempInputs):    isFunction = False    if isinstance(function, dict):        for eveKey, eveValue in function.items():            if eveKey == "Type" and eveValue == "TencentCloud::Serverless::Function":                isFunction = True        if isFunction:            for eveKey, eveValue in function.items():                if eveKey == "Type" and eveValue == "TencentCloud::Serverless::Function":                    continue                else:                    tempInputs = getBaseFunctionComponents(eveValue, functionName, tempInputs)                    serverlessPluginYaml = {                        "component": '@serverless/tencent-scf',                        "inputs": tempInputs                    }                    return serverlessPluginYaml        else:            return Falsedef getEventPlugin(eventType, eventName, eventSource, deepList=[]):    tempEvent = {}    tempEvent[eventType] = {        "name": eventName,        "parameters": {}    }    tempParameter = {}    for eveParameterKey, eveParameterValue in eventSource["Properties"].items():        tempKey = str.lower(eveParameterKey[0]) + eveParameterKey[1:]        if deepList and eveParameterKey in deepList:            tempDeepData = {}            for eveFilterKey, eveFilterValue in eveParameterValue.items():                tempThisKey = str.lower(eveFilterKey[0]) + eveFilterKey[1:]                tempDeepData[tempThisKey] = eveFilterValue            tempParameter[tempKey] = tempDeepData            continue        tempParameter[tempKey] = eveParameterValue    tempEvent[eventType]["parameters"] = tempParameter    return tempEventdef getBaseFunctionPlugin(functionInformation, functionName=None, tempInputs=None):    tempInputs = tempInputs if tempInputs else {}    if functionName:        tempInputs["name"] = functionName    if isinstance(functionInformation, dict):        for eveFunctionKey, eveFunctionValue in functionInformation.items():            if eveFunctionKey not in ["Events", "Environment", "VpcConfig", "Type", "Role"]:                tempKey = str.lower(eveFunctionKey[0]) + eveFunctionKey[1:]                tempInputs[tempKey] = eveFunctionValue            else:                if eveFunctionKey == "Environment":                    if eveFunctionValue and "Variables" in eveFunctionValue:                        tempEnvironment = {                            "variables": eveFunctionValue["Variables"]                        }                        tempInputs["environment"] = tempEnvironment                elif eveFunctionKey == "VpcConfig":                    tempVpcConfig = {}                    if eveFunctionValue and "SubnetId" in eveFunctionValue:                        tempSubnetId = eveFunctionValue["SubnetId"]                        tempVpcConfig["subnetId"] = tempSubnetId                    if eveFunctionValue and "VpcId" in eveFunctionValue:                        tempVpcId = eveFunctionValue["VpcId"]                        tempVpcConfig["vpcId"] = tempVpcId                    tempInputs["vpcConfig"] = tempVpcConfig                elif eveFunctionKey == "Events":                    tempEvents = []                    if isinstance(eveFunctionValue, dict):                        for eveEventKey, eveEventValue in eveFunctionValue.items():                            if isinstance(eveEventValue["Properties"], dict):                                tempEvent = {}                                if eveEventValue["Type"] == "APIGW":                                    tempEvent = getEventPlugin("apigw", eveEventKey, eveEventValue)                                elif eveEventValue["Type"] == "COS":                                    tempEvent = getEventPlugin("cos", eveEventKey, eveEventValue, ["Filter"])                                elif eveEventValue["Type"] == "Timer":                                    tempEvent = getEventPlugin("timer", eveEventKey, eveEventValue)                                elif eveEventValue["Type"] == "CMQ":                                    tempEvent['cmq'] = getEventPlugin("cmq", eveEventKey, eveEventValue)                                elif eveEventValue["Type"] == "CKafka":                                    tempEvent = getEventPlugin("ckafka", eveEventKey, eveEventValue)                                tempEvents.append(tempEvent)                    if tempEvents:                        tempInputs["events"] = tempEvents    return tempInputsdef getFunctionPlugin(functionName, function, tempInputs):    isFunction = False    if isinstance(function, dict):        for eveKey, eveValue in function.items():            if eveKey == "Type" and eveValue == "TencentCloud::Serverless::Function":                isFunction = True        if isFunction:            for eveKey, eveValue in function.items():                if eveKey == "Type" and eveValue == "TencentCloud::Serverless::Function":                    continue                else:                    return getBaseFunctionPlugin(eveValue, functionName, tempInputs)        else:            return Falsedef doComponents(scfYaml):    try:        yamlData = yaml.load(scfYaml)        functions = {}        if "Globals" in yamlData:            inputs = getBaseFunctionComponents(yamlData["Globals"]["Function"])        if isinstance(yamlData['Resources'], dict):            for eveKey, eveValue in yamlData['Resources'].items():                for eveNamespaceKey, eveNamespaceValue in eveValue.items():                    tempInputs = inputs.copy()                    if eveNamespaceKey == "Type" and eveNamespaceValue == "TencentCloud::Serverless::Namespace":                        continue                    tempFunction = getFunctionComponents(eveNamespaceKey, eveNamespaceValue, tempInputs)                    if tempFunction:                        functions[eveNamespaceKey] = tempFunction        return {            "error": False,            "result": yaml.safe_dump(functions)        }    except:        return {            "error": True,            "result": "Scf Yaml未能正常轉換為Serverless Component Yaml"        }def doPlugin(scfYaml):    try:        yamlData = yaml.load(scfYaml)        # 獲取Provider        print("獲取Provider")        if "Globals" in yamlData:            provider = getBaseFunctionPlugin(yamlData["Globals"]["Function"])        provider["name"] = "tencent"        provider["credentials"] = "~/credentials"        # 獲取service        print("獲取Service")        service = "Tencent-Serverless-Framework"        # 獲取插件        print("獲取Plugin")        plugin = ["serverless-tencent-scf"]        # 獲取函數        print("獲取Function")        functions = {}        if isinstance(yamlData['Resources'], dict):            for eveKey, eveValue in yamlData['Resources'].items():                for eveNamespaceKey, eveNamespaceValue in eveValue.items():                    tempInputs = {}                    if eveNamespaceKey == "Type" and eveNamespaceValue == "TencentCloud::Serverless::Namespace":                        continue                    tempFunction = getFunctionPlugin(eveNamespaceKey, eveNamespaceValue, tempInputs)                    if tempFunction:                        functions[eveNamespaceKey] = tempFunction        serverlessJson = {            "service": service,            "provider": provider,            "plugins": plugin,            "functions": functions        }        return {            "error": False,            "result": yaml.safe_dump(serverlessJson)        }    except Exception as e:        print(e)        return {            "error": True,            "result": "Scf Yaml未能正常轉換為Serverless Plugin Yaml"        }/<code>

是的,就是這麼粗暴,上來就扔代碼。

使用方法很簡單,如果是轉Plugin:

<code>pluginYaml = doPlugin(scfYaml)/<code>

如果是轉Component:

<code>componentYaml = doComponent(scfYaml)/<code>

代碼不是很好看,但是可以用,所以各位大佬輕噴就好。另外代碼開源了,可以參考:https://github.com/anycodes/ServerlessPractice/tree/master/scf_2_serverless


從SCFCLI/SCF VSCode遷移過渡到Serverless Framework


分享到:


相關文章: