当前位置: 首页 > 后端技术 > Python

py-libterraform 的使用和实现:一个 Terraform 的 Python 绑定_0

时间:2023-03-26 19:46:15 Python

py-libterraform鐨勪娇鐢ㄥ拰瀹炵幇锛氫竴涓狿ythonbindingforTerraform鍒濊》鏄湪浣跨敤Python寮€鍙戠殑涓氬姟涓紝娑夊強鍒癟erraform鐨勪氦浜掋€傚叿浣撻渶姹傛湁涓や釜锛氶渶瑕佽皟鐢═erraform鐨勫悇绉嶅懡浠ゅ畬鎴愯祫婧愰儴缃插拰閿€姣佺瓑鎿嶄綔锛岄渶瑕佽В鏋怲erraform鐨勯厤缃枃浠讹紙HCL璇硶锛夊浜庡墠鑰咃紝鏈変竴涓紑婧愬簱锛屽悕瀛楀彨python-terraform锛屽畠灏佽浜員erraform鐨勫懡浠ゃ€傚綋鎴戜滑鍦ㄤ唬鐮佷腑璋冪敤瀹冧滑鏃讹紝浼氬惎鍔ㄤ竴涓柊鐨勮繘绋嬫潵鎵цTerraform鐩稿簲鐨勫懡浠わ紝骞朵笖鍙互杩斿洖鍛戒护鐨勯€€鍑虹爜鍜屾崟鑾风殑stdout鍜宻tderr銆俻ython-terraform铏界劧浣跨敤鏂逛究锛屼絾鏄渶澶х殑缂虹偣鏄渶瑕佹彁鍓嶅湪鎵ц鐜涓畨瑁匱erraform锛屾柊鐨勮繘绋嬩篃甯︽潵浜嗛澶栫殑寮€閿€銆傚浜庡悗鑰咃紝鐩墠杩樻病鏈夋壘鍒扮鍚堣姹傜殑Python寮€婧愬簱銆傚笇鏈涙湁涓€涓簱鍙互鍦ㄥ綋鍓嶈繘绋嬩腑鎵цTerraform鍛戒护鑰屼笉闇€瑕佺敤鎴锋彁鍓嶅畨瑁匱erraform锛岃繕鍙互瑙f瀽Terraform閰嶇疆鏂囦欢锛屼簬鏄痯y-libterraform璇炵敓浜嗐€傚湪璁茶Вpy-libterraform鐨勫疄鐜板師鐞嗕箣鍓嶏紝鎴戜滑鍏堟潵鐪嬬湅濡備綍瀹夎鍜屼娇鐢ㄥ畠銆傚畠鐨勫畨瑁呴潪甯哥畝鍗曪紝鎵цpip鍛戒护鍗冲彲锛屾敮鎸丮ac銆丩inux鍜學indows锛屾敮鎸丳ython3.6鍙婁互涓婏細$pipinstalllibterraformpy-libterraform鐩墠鎻愪緵涓や釜鍔熻兘锛歍erraformCommand鐢ㄤ簬鎵цTerraformCLI锛孴erraformConfig鐢ㄤ簬瑙f瀽Terraform閰嶇疆鏂囦欢銆傝繖涓や釜鍑芥暟鍚庨潰浼氫妇渚嬭鏄庛€傚亣璁惧綋鍓嶆湁涓€涓猻leep鏂囦欢澶癸紝閲岄潰鐨刴ain.tf鏂囦欢鍐呭濡備笅锛歷ariable"time1"{type=stringdefault="1s"}variable"time2"{type=stringdefault="1s"}resource"time_sleep""wait1"{create_duration=var.time1}resource"time_sleep""wait2"{create_duration=var.time2}output"wait1_id"{value=time_sleep.wait1.id}output"wait2_id"{value=time_sleep.wait2.id}Terraform鐜板湪CLI杩涘叆sleep鐩綍锛岄渶瑕佹墽琛孴erraforminit,apply鍜宻how鍦ㄤ笂闈㈤儴缃茶祫婧愬拰鏌ョ湅璧勬簮灞炴€э紝鐒跺悗鍙互杩欐牱鍋氾細>>>fromlibterraformimportTerraformCommand>>>cli=TerraformCommand()>>>cli銆俰nit()>>>_.value'\n姝e湪鍒濆鍖栧悗绔?..\n\n姝e湪鍒濆鍖栨彁渚涚▼搴忔彃浠?..\n-浠庝緷璧栭攣鏂囦欢涓噸鏂颁娇鐢ㄤ互鍓嶇増鏈殑hashicorp/time\n-浣跨敤涔嬪墠瀹夎鐨刪ashicorp/timev0.7.2\n\nTerraform宸叉垚鍔熷垵濮嬪寲锛乗n\n鎮ㄧ幇鍦ㄥ彲浠ュ紑濮嬩娇鐢═erraform銆傚皾璇曡繍琛屸€渢erraformplan鈥濅互鏌ョ湅\n鎮ㄧ殑鍩虹鏋舵瀯鎵€闇€鐨勪换浣曟洿鏀广€傛墍鏈塗erraform鍛戒护\n鐜板湪閮藉簲璇ュ彲浠ュ伐浣滀簡銆俓n\n濡傛灉鎮ㄦ浘涓篢erraform璁剧疆鎴栨洿鏀规ā鍧楁垨鍚庣閰嶇疆锛孿n璇烽噸鏂拌繍琛屾鍛戒护浠ラ噸鏂板垵濮嬪寲鎮ㄧ殑宸ヤ綔鐩綍銆傚鏋滄偍蹇樿浜嗭紝\n鍏朵粬鍛戒护浼氭娴嬪埌瀹冨苟鍦ㄥ繀瑕佹椂鎻愰啋鎮ㄨ繖鏍峰仛銆俓n'>>>cli.apply()>>>_.value[{'@level':'info','@message':'Terraform1.1.7','@module':'terraform.ui','@timestamp':'2022-04-08T19:16:59.984727+08:00','terraform':'1.1.7','type':'version','ui':'1.0'},...]>>>cli.show()>>>_.value{'format_version':'1.0','terraform_version':'1.1.7','values':{'outputs':{'wait1_id':{'sensitive':False,'value':'2022-04-08T11:17:01Z'},'wait2_id':{'sensitive':False,'value':'2022-04-08T11:17:01Z'}},'root_module':{'resources':[{'address':'time_sleep.wait1','mode':'managed','type':'time_sleep','name'锛?wait1'锛?provider_name'锛?registry.terraform.io/hashicorp/time'锛?schema_version'锛?锛?values'锛歿'create_duration'锛?1s'锛?destroy_duration'锛氭棤锛?id':'2022-04-08T11:17:01Z','triggers':None},'sensitive_values':{}},{'address':'time_sleep.wait2','mode':'managed','type':'time_sleep','name':'wait2','provider_name':'registry.terraform.io/hashicorp/time','schema_version':0,'values':{'create_duration':'1s','destroy_duration':None,'id':'2022-04-08T11:17:01Z','triggers':None},'sensitive_values':{}}]}}}浠庝笂闈㈢殑鎵ц杩囩▼鍙互鐪嬪嚭鏃犺鎵ц浠讳綍鍛戒护閮戒細杩斿洖涓€涓狢ommandResult瀵硅薄锛岃瀵硅薄鐢ㄤ簬琛ㄧず鍛戒护鎵ц缁撴灉锛堝寘鎷繑鍥炵爜銆佽緭鍑恒€侀敊璇緭鍑恒€佹槸鍚︿负json缁撴瀯锛夈€傚叾涓細init()杩斿洖鐨勫€兼槸Terraforminit鍛戒护鐨勬爣鍑嗚緭鍑猴紝涓€涓猻tringapply()杩斿洖鐨勫€奸粯璁や负Terraformapply-json鍛戒护鐨勬爣鍑嗚緭鍑猴紝瑙嗕负json鍔犺浇鍚庣殑鏁版嵁锛屾樉绀烘棩蹇楄褰曠殑鍒楄〃銆傚鏋滀笉鎯宠В鏋愭爣鍑嗚緭鍑猴紝鍙互浣跨敤apply(json=False)show()杩斿洖鐨勫€奸粯璁や负Terraformshow-jon鍛戒护鐨勬爣鍑嗚緭鍑鸿瑙嗕负json鍔犺浇鍚庣殑鏁版嵁锛宎鏄剧ずTerraform鐘舵€佹枃浠舵暟鎹粨鏋勭殑瀛楀吀瀵规墍鏈夊懡浠ゅ皝瑁呭嚱鏁扮殑鎬濇兂鏄负浜嗚绋嬪簭澶勭悊鐨勭粨鏋滃敖鍙兘鏂逛究锛屾墍浠ュ浜庢敮鎸?json鐨凾erraform鍛戒护锛屼細浣跨敤杩欎釜閫夐」榛樿鍊硷紝缁撴灉灏嗚瑙f瀽銆備笂闈㈡槸涓€涓畝鍗曠殑渚嬪瓙銆傚疄闄呬笂锛孴erraformCommand灏佽浜嗘墍鏈夌殑Terraform鍛戒护銆傛偍鍙互璋冪敤help(TerraformCommand)浜嗚В璇︽儏銆俆erraform閰嶇疆鏂囦欢瑙f瀽濡傛灉鎯宠Terraform瀵归厤缃枃浠剁殑瑙f瀽缁撴灉杩涜杩涗竴姝ョ殑澶勭悊锛岄偅涔圱erraformConfig灏卞彲浠ユ弧瓒抽渶姹傦紝閫氳繃瀹冨彲浠ヨВ鏋愭寚瀹氱殑Terraform閰嶇疆鐩綍锛岃幏鍙栧彉閲忋€佽祫婧愩€佽緭鍑恒€佽鍙风瓑鍏朵腑鐨勪俊鎭€傝繖瀵逛簬鍒嗘瀽閰嶇疆缁勫悎寰堟湁鐢ㄣ€備綘鍙互杩欐牱鍋氾紙閮ㄥ垎杈撳嚭鐢ㄥ緱姣旇緝澶氣€︹€︾渷鐣ワ級锛?>>fromlibterraformimportTerraformConfig>>>mod,_=TerraformConfig.load_config_dir('.')>>>mod{'SourceDir':'.'锛?CoreVersionConstraints'锛氭棤锛?ActiveExperiments'锛歿}锛?鍚庣'锛氭棤锛?CloudConfig'锛氭棤锛?ProviderConfigs'锛氭棤锛?ProviderRequirements'锛歿'RequiredProviders'锛歿}锛?DeclRange'锛氥€?.},'鍙橀噺':{'time1':...,'time2':...},'灞€閮ㄥ彉閲?:{},'杈撳嚭':{'wait1_id':...,'wait2_id':...},'ModuleCalls':{},'ManagedResources':{'time_sleep.wait1':...,'time_sleep.wait2':...},'DataResources':{},'Moved':鏃爙TerraformConfig.load_config_dir浼氳皟鐢═erraform婧愮爜涓璱nternal/configs/parser_config_dir.go涓殑LoadConfigDir鏂规硶鍔犺浇Terraform閰嶇疆鏂囦欢鐩綍锛岃繑鍥炲唴瀹逛负鍘熺敓杩斿洖缁撴灉*Module锛宧cl.Diagnostics琚簭鍒楀寲鍔犺浇鍒癙ython涓垎鍒湁瀛楀吀銆傚疄鐜板師鐞嗙敱浜嶵erraform鏄敤GoLang缂栧啓鐨勶紝Python鏃犳硶鐩存帴璋冪敤锛屽垢濂藉彲浠ョ紪璇戞垚鍔ㄦ€侀摼鎺ュ簱锛屽啀鐢盤ython鍔犺浇璋冪敤銆傚洜姝わ紝涓€鑸儏鍐典笅锛屽彲浠ヨ繖鏍峰仛锛氫娇鐢╟go缂栧啓Terraform鐨凜鎺ュ彛鏂囦欢锛岀紪璇戞垚鍔ㄦ€侀摼鎺ュ簱锛屽湪Linux/Unix涓婁互.so缁撳熬锛屽湪Windows涓婁互.dll缁撳熬銆傞€氳繃Python搴撲腑鐨刢type鍔犺浇杩欎釜鍔ㄦ€侀摼鎺ワ紝鍦ㄥ叾涓婂疄鐜板懡浠ゅ皝瑁呫€備粠鏈川涓婅锛孏oLang鍜孭ython閮芥槸浠涓哄獟浠嬫潵瀹屾垚浜や簰鐨勩€傜綉涓婃湁寰堝鍏充簬濡備綍浣跨敤cgo鍜宑types鐨勬枃绔犮€傛湰鏂囩潃閲嶄粙缁嶅疄鐜拌繃绋嬩腑閬囧埌鐨勫悇绉嶁€滃潙鈥濓紝浠ュ強濡備綍瑙e喅銆傚潙涓€锛欸oLang鍐呴儴鐨勫寘鏈哄埗闃诲浜嗗閮ㄨ皟鐢ㄣ€侴oLang浠?.4鐗堟湰寮€濮嬪姞鍏ヤ簡鍐呴儴鍖呮満鍒讹紝鍙厑璁稿鍏ュ唴閮ㄧ埗鐩綍鍜岀埗鐩綍鐨勫瓙鍖咃紝涓嶈兘瀵煎叆鍏朵粬鍖呫€傚湪鏈€鏂扮増鏈殑Terraform涓紝鍑犱箮鎵€鏈夌殑浠g爜閮芥斁鍦ㄤ簡internal涓紝涔熷氨鏄濡傛灉灏哻go缂栧啓鐨勬帴鍙f枃浠讹紙鏈」鐩腑绉颁负libterraform.go锛変綔涓哄閮ㄥ寘锛堜緥濡傚寘鍚嶄负libterraform锛夛紝鏃犳硶璋冪敤Terraform浠g爜锛屾棤娉曞疄鐜癟erraform鍛戒护鐨勫皝瑁呫€備竴涓В鍐虫柟妗堟槸鍦═erraform涓皢internal鏀逛负public锛屼絾杩欐剰鍛崇潃闇€瑕佷慨鏀瑰ぇ閲忕殑Terraform婧愪唬鐮侊紝杩欎笉鏄竴涓ソ涓绘剰銆傞偅涔堝彟涓€涓兂娉曟槸璁﹍ibterraform.go鎴愪负鏁翠釜Terraform椤圭洰鐨勨€滀竴閮ㄥ垎鈥濇潵鈥滄楠椻€滸o缂栬瘧鍣ㄣ€傚叿浣撹繃绋嬪涓嬶細libterraform.go鐨勫寘鍚嶄笌Terraform涓诲寘涓€鑷达紝鍗冲湪涓绘瀯寤哄墠锛屽皢libterraform.go绉诲姩鍒癟erraform婧愮爜鏍圭洰褰曚笅銆備互Terraform椤圭洰鎴愬憳韬唤鏋勫缓鏃讹紝浣跨敤gobuild-buildmode=c-shared-o=libterraform.sogithub.com/hashicorp/terraform鍛戒护杩涜缂栬瘧锛岃繖鏍风紪璇戝嚭鏉ョ殑鍔ㄦ€侀摼鎺ュ簱鍙互鍖呭惈libterraform鐨勯€昏緫鍧?go2锛氭敞鎰忕鐞咰杩愯鏃剁敵璇风殑鍐呭瓨绌洪棿锛屼笉绠℃槸GoLang杩樻槸Python锛屾垜浠兘涓嶉渶瑕佹媴蹇冨唴瀛樼鐞嗭紝鍥犱负瀹冧滑浼氬湪鍚堥€傜殑鏃跺€欒璇█鐨勫瀮鍦惧洖鏀跺洖鏀舵満鍒躲€備絾鏄秹鍙婂埌C鐨勯€昏緫锛屽氨闇€瑕佹敞鎰忓唴瀛樼鐞嗕簡銆備娇鐢╟go涓畾涔夌殑鎺ュ彛鍙兘浼氳繑鍥?C.char锛岃繖瀹為檯涓婃槸鍦–灞傞潰寮€杈熺殑涓€娈靛唴瀛樼┖闂达紝闇€瑕佹樉寮忛噴鏀俱€備緥濡俵ibterraform.go瀹氫箟浜嗘柟娉旵onfigLoadConfigDir鍔犺浇Terraform閰嶇疆鐩綍锛屽疄鐜板涓嬶細//exportConfigLoadConfigDirfuncConfigLoadConfigDir(cPath*C.char)(cMod*C.char,cDiags*C.char,cError*C.char){deferfunc(){recover()}()parser:=configs.NewParser(nil)path:=C.GoString(cPath)mod,diags:=parser.LoadConfigDir(path)modBytes,err:=json.Marshal(convertModule(mod))iferr!=nil{cMod=C.CString("")cDiags=C.CString("")cError=C.CString(err.Error())杩斿洖cMod,cDiags,cError}diagsBytes,err:=json.Marshal(diags)濡傛灉err!=nil{cMod=C.CString(string(modBytes))cDiags=C.CString("")cError=C.CString(err.Error())returncMod,cDiags,cError}cMod=C.CString(string(modBytes))cDiags=C.CString(string(diagsBytes))cError=C.CString("")returncMod,cDiags,cError}鍦ㄦ墽琛屼腑涓婇潰鐨勬柟娉曪紝浣跨敤C.CString浼氬湪鍦–灞傞潰鐢宠涓€鍧楀唴瀛樼┖闂达紝骞跺皢缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝閭d箞璋冪敤鑰咃紙Python杩涚▼锛夊湪浣跨敤杩斿洖鍊煎悗闇€瑕佹樉寮忛噴鏀惧唴瀛樺湪姝や箣鍓嶏紝闇€瑕侀€氳繃cgo鏆撮湶閲婃斁鍐呭瓨鐨勬柟娉曪細//exportFreefuncFree(cString*int){C.free(unsafe.Pointer(cString))}鐒跺悗鍦≒ython涓彲浠ュ疄鐜板涓嬪皝瑁咃細importosfromctypes浠巐ibterraform.common瀵煎叆WINDOWS绫籐oadConfigDirResult锛堢粨鏋勶級锛?loadargconfig[c_char_p]_load_config_dir.restype=LoadConfigDirResultroot=os.path.dirname(os.path.abspath(__file__))_lib_filename='libterraform.dll'ifWINDOWSelse'libterraform.so'_lib_tf=cdll.LoadLibrary(os.path.join(root,_lib_filename))_free=_lib_tf.Free_free.argtypes=[c_void_p]defload_config_dir(path:str)->(dict,dict):ret=_load_config_dir(path.encode('utf-8'))r_mod=cast(ret.r0,c_char_p).value_free(ret.r0)r_diags=cast(ret.r1,c_char_p).value_free(ret.r1)err=cast(ret.r2,c_char_p).value_free(ret.r2)...杩欓噷锛屽緱鍒拌繑鍥炵粨鏋滃悗锛岃皟鐢╛free锛堝嵆libterraform.go涓殑Free锛夋樉寮忛噴鏀惧唴瀛橈紝閬垮厤鍐呭瓨娉勬紡鍧?锛氭崟鑾疯緭鍑哄湪Terraform鐨勬簮鐮佷腑锛屾墽琛屽懡浠ょ殑杈撳嚭浼氳鎵撳嵃鍒版爣鍑嗚緭鍑簊tdout鍜屾爣鍑嗛敊璇緭鍑簊tderr锛岀劧鍚庝娇鐢╟go灏佽RunCli鎺ュ彛锛屽綋琚玃ython璋冪敤鏃讹紝鐩存帴杈撳嚭鍒伴粯璁や负鏍囧噯杈撳嚭鍜屾爣鍑嗛敊璇€傝繖鏈変粈涔堥棶棰樺悧锛熷鏋滃悓鏃舵墽琛屼袱鏉″懡浠わ紝杈撳嚭缁撴灉浼氫氦閿欙紝鏃犳硶鍖哄垎缁撴灉鏉ヨ嚜鍝潯鍛戒护銆傝В鍐虫柟娉曟槸浣跨敤绠¢亾锛氬湪Python杩涚▼涓娇鐢╫s.pipe鍒嗗埆涓烘爣鍑嗚緭鍑哄拰鏍囧噯閿欒杈撳嚭鍒涘缓绠¢亾锛堜細鐢熸垚鏂囦欢鎻忚堪绗︼級锛屽皢杩欎袱涓枃浠舵弿杩扮浼犲叆libterraform.go鐨凴unCli鏂规硶涓€傚唴閮ㄤ娇鐢╫s.NewFile鎵撳紑涓や釜鏂囦欢鎻忚堪绗﹀苟鍒嗗埆鏇挎崲os.Stdout鍜宱s.Stderr鍦≧unCli鏂规硶缁撴潫鏃跺叧闂繖涓や釜鏂囦欢骞舵仮澶嶅師鏉ョ殑os.Stdout鍜宱s.Stderr鍚屾牱锛屼娇鐢╫s.浣跨敤pipe鑾峰彇鐨勬枃浠舵弿杩扮缁檒ibterraform.go鏃讹紝娉ㄦ剰鎿嶄綔绯荤粺鐨勫尯鍒細瀵逛簬Linux/Unix锛屽彲浠ョ洿鎺ヤ紶杩涘幓浣跨敤锛涘浜嶹indows锛岄渶瑕佸皢鏂囦欢鎻忚堪绗﹁浆鎹㈡垚鏂囦欢鍙ユ焺锛岃繖鏄洜涓篧indows涓奊oLang鐨刼s.NewFile鎺ユ敹鐨勬槸鏂囦欢鍙ユ焺銆侾ython涓浉鍏充唬鐮佸涓嬶細ifWINDOWS:importmsvcrtw_stdout_handle=msvcrt.get_osfhandle(w_stdout_fd)w_stderr_handle=msvcrt.get_osfhandle(w_stderr_fd)retcode=_run_cli(argc,c_w_stdout_handle,w_stderr_handle)else:c_cliarg=_crun,w_stdout_fd,w_stderr_fd)鍧?锛歅ipeHang鐢变簬pipe鐨勫ぇ灏忛檺鍒讹紝濡傛灉鍐欏叆瓒呰繃闄愬埗锛屼細瀵艰嚧writeHang銆傛墍浠ヨ皟鐢≧unCli鍚庝笉鑳借鍙栫閬撲腑鐨勮緭鍑猴紙鍗冲懡浠よ緭鍑轰細鍐欏叆绠¢亾锛夛紝鍚﹀垯浣犱細鍙戠幇鎵ц绠€鍗曞懡浠わ紙濡倂ersion锛夋椂姝e父锛屼絾鎵ц澶嶆潅鍛戒护鏃跺懡浠わ紙姣斿apply锛屽洜涓烘湁寰堝杈撳嚭锛夋湁鏃跺€欎細hanglive銆傝В鍐虫柟娉曟槸鍦ㄨ皟鐢≧unCli涔嬪墠鍚姩涓や釜绾跨▼鍒嗗埆璇诲彇鏍囧噯杈撳嚭鍜屾爣鍑嗛敊璇緭鍑虹殑鏂囦欢鎻忚堪绗﹀唴瀹癸紝璋冪敤RunCli鍛戒护鍚庡姞鍏ヨ繖涓や釜绾跨▼銆侾ython涓浉鍏充唬鐮佸涓嬶細r_stdout_fd,w_stdout_fd=os.pipe()stdout_buffer))stdout_thread.daemon=Truestdout_thread.start()stderr_thread=Thread(target=cls._fdread,args=(r_stderr_fd,stderr_buffer))stderr_thread.daemon=Truestderr_thread.start()濡傛灉WINDOWS:importmsvcrtw_stdout_handle=msvcrt.get_osfhandle(w_stdout_fd)w_stderr_handle=msvcrt.get_osfhandle(w_stderr_fd)retcode=_run_cli(argc,c_argv,w_stdout_handle,w_stderr_handle)else:retcode=_run_cli(argc,c_argv,w_stdout_fd,w_stderrif_thread()stdoutbur_thread()raiseTerraformFdReadError(fd=r_stdout_fd)ifnotstderr_buffer:raiseTerraformFdReadError(fd=r_stderr_fd)stdout=stdout_buffer[0]stderr=stderr_buffer[0]鏈€鍚庯紝褰撳彂鐜扮幇鏈夌殑寮€婧愬簱涓嶈兘婊¤冻闇€姹傛椂锛屾垜绔檙tedpy-libterraform锛屽熀鏈疄鐜颁簡鍗曡繘绋嬭皟鐢═erraform鍛戒护鐨勯渶姹傘€傝櫧鐒跺湪寮€鍙戣繃绋嬩腑閬囧埌浜嗗悇绉嶅悇鏍风殑闂锛岄渶瑕佷笉鏂湪Python銆丟oLang銆丆涔嬮棿璺虫潵璺冲幓锛屼絾濂藉湪閮戒竴涓€瑙e喅浜嗐€傚鏋滄妸杩欎釜杩囩▼璁板綍涓嬫潵锛岃兘璁╁ぇ瀹跺厤浜庘€滆俯鍧戔€濓紝閭e氨澶€间簡锛佹渶鍚庯紝https://github.com/Prodesire/...姹傚ソ璇勷煒剘