从SCFCLI/SCF VSCode迁移过渡到Serverless Framework

SCFCLI和VSCode的插件很早之前就有了,也有很多用户在使用这两个工具, 使用它们可以通过已经写的Yaml直接把函数部署到线上,非常方便。但是眼尖的小伙伴已经发现这样一件事:SCFCLI和VSCode插件貌似很久都没更新了,而且云函数的小伙伴在极力推动大家使用Serverless Framework??梢钥吹絊CFCLI在6月份的时候更新频繁,而现在,更新缓慢。

同时,细心的小伙伴还发现了,Serverless Framework貌似比SCFCLI好用??!因为它不仅仅可以部署函数,还可以部署APIGW,COS,CDN......最主要,通过Serverless Frameworek还可以快速的把常用的框架,例如Express、Flask、Django.....等直接部署到云函数上,这是多方便的一件事情?。?/p>

就问还在用SCFCLI的小伙伴,你们酸没酸?

有的小伙伴在跃跃欲试之后,终于下定决心,将SCFCLI放弃掉,开始使用Serverless Framework,那么问题来了,这两个东西的Yaml写的不一样,是完全不一样,那么应该如何把已有的SCFCLI/VSCode插件的Yaml快速转换成为Serverless Framework的Yaml呢?

下面就是几个简单的实现方法:

通过网页进行转换

作为社区爱好者,我必然要提供一个简单的网页,来做这个事情:

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

通过这个网址,你只需要输入基于SCFCLI的Yaml,就可以快速转换:

image

转换结果是可以同时生成Component的Yaml和Plugin的Yaml

通过接口自主转换

接口地址:

输入参数:yaml,字符串类型,就是之前SCFCLI/VSCODE插件的Yaml内容

输出参数:error,布尔类型,是否出错;result,字符串类型,结果(error为true,此处输出错误信息,为false时输出新的yaml结果)

以Python语言为例,将原有的Yaml转换成为Component的Yaml可以这样操作:

import urllib.request
import json

with 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'])

这样就可以把已有的SCFCLI Yaml转换成Serverless Component的Yaml了,Plugin的转换方法同理,只需要更换一个一下url地址就好了。

自己写本地脚本来转

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 tempInputs


def 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 False


def 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 tempEvent


def 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 tempInputs


def 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 False


def 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"
        }

是的,就是这么粗暴,上来就扔代码。

使用方法很简单,如果是转Plugin:

pluginYaml = doPlugin(scfYaml)

如果是转Component:

componentYaml = doComponent(scfYaml)

代码不是很好看,但是可以用,所以各位大佬轻喷就好。另外代码开源了,可以参考:https://github.com/anycodes/ServerlessPractice/tree/master/scf_2_serverless


image
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351

推荐阅读更多精彩内容