当前位置 :首页 >> 综艺

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

2023-03-01   来源 : 综艺

commandsshould now work.If you ever set or change modules or backend configuration for Terraform,rerun this command to reinitialize your working directory. If you forget, othercommands will detect it and remind you to do so if necessary.'>>> cli.apply>>> _.value[{'@level': 'info', '@message': 'Terraform 1.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': 0, 'values': {'create_duration': '1s', 'destroy_duration': None, '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': {}}]}}}

从上述分派流程可以可知,不论分派什么立即,都才会来到一个 CommandResult单纯,用来表示立即分派结果(纸制含来到编码、输入、偏差输入、是否为 json 结构)。其中都:

init来到的 value 是 Terraform init立即的标准规范输入,一个字符串

apply来到的 value 预设是 Terraform apply -json立即的标准规范输入被视作 json 启动时后的数据,一个展览品日志历史纪录的列表。如果不决心类比标准规范输入,则可以应运用于 apply(json=False)

show来到的 value 预设是 Terraform show -jon立即的标准规范输入被视作 json 启动时后的数据,一个展览品 Terraform state 机密文件数据结构的注解

所有立即的积体电路函数的思路是尽量让结果不便给程序处理,因此对于反对 -json的 Terraform 立即都才会预设应运用于此选项并对结果展开类比。

以上是一个直观的示例,实质上上 TerraformCommand积体电路了所有的 Terraform 立即,具体可以多线程 help(TerraformCommand)展开查询。

▌Terraform 可用机密文件类比

如果决心丢掉 Terraform 对可用机密文件的类比结果认真大幅度处理,那么 TerraformConfig就可以保证需求,通过它可以类比自行决定的 Terraform 可用参考资料,给与其中都的变量、人力资源、输入、公家机关等数据,这对分析可用均是由很有试图。可以这么认真(部分输入多数应运用于...认真了省略):

>>> fromlibterraform importTerraformConfig>>> mod, _ = TerraformConfig.load_config_dir('.')>>> mod{'SourceDir': '.', 'CoreVersionConstraints': None, 'ActiveExperiments': {}, 'Backend': None, 'CloudConfig': None, 'ProviderConfigs': None, 'ProviderRequirements': {'RequiredProviders': {}, 'DeclRange': ...}, 'Variables': {'time1': ..., 'time2': ...}, 'Locals': {}, 'Outputs': {'wait1_id': ..., 'wait2_id': ...}, 'ModuleCalls': {}, 'ManagedResources': {'time_sleep.wait1': ..., 'time_sleep.wait2': ...}, 'DataResources': {}, 'Moved': None}

TerraformConfig.load_config_dir看似才会多线程 Terraform OpenBSD中都 internal/configs/parser_config_dir.go中都的 LoadConfigDir新方法,以启动时 Terraform 可用机密文件参考资料,来到内容是原生来到结果 *Module, hcl.Diagnostics的经序列化后分别启动时为 Python 中都的注解。

假定原理

由于 Terraform 是用 GoLang 编撰的,Python 很难这样一来多线程,但好在它可以程式编码为动态链接坎,然后于是又被 Python 启动时多线程。因此,相比之下思路上可以这么认真:

应运用于 cgo编撰 Terraform 的 C API机密文件

将它程式编码为动态链接坎,Linux/Unix 上以 .so结尾处,在 Windows 上以 .dll结尾处

在 Python 中都通过 ctypes启动时此动态链接坎,在此之下假定立即积体电路

本质上,GoLang 和 Python 两者之间以 C 作为媒介,下回成交互。关于如何应运用于 cgo和 ctypes网上有很多文章,本文着重详述假定流程中都遇到的各种“陨”以及如何克服的。

▌陨 1:GoLang 的 internal packages 系统阻隔了本体多线程

GoLang 从 1.4 版开始,增加了 Internal packages 系统,只允许 internal 的父级参考资料及父级参考资料的兄纸制为基础,其它纸制很难为基础。而 Terraform 最新版中都,几乎所有的标识符都放在了 internal 中都,这假定应运用于 cgo写到的API机密文件(本这两项中都叫 libterraform.go)如果作为本体纸制(比如纸制据称 libterraform)是很难多线程 Terraform 标识符的,也就很难假定 Terraform 立即的积体电路。

一个克服新方法是把 Terraform 中都的 internal 改 public,但这假定并不需要修改大量的 Terraform OpenBSD,这可不是个好主意。

那么另一个思路就是让 libterraform.go作为整个 Terraform 这两项的“一份兄”,来“掩饰” Go 程式编码器。具体流程如下:

libterraform.go的纸制名和 Terraform 主纸制保持一致,即 main

构建前把 libterraform.go快速移动到 Terraform OpenBSD根参考资料下,作为 Terraform 这两项的成员

构建时,应运用于 go build -buildmode=c-shared -o=libterraform.so github.com/hashicorp/terraform立即展开程式编码,这样程式编码出新的动态链接坎就能纸制含 libterraform.go的命题

▌陨 2:肯定管理 C 行驶时申商量的闪存空间

不论是 GoLang 还是 Python,我们都不并不需要担心闪存管理的疑问,因为它们自才会被语言的污泥回收系统在合适的时机去回收。但是限于到 C 的命题就并不需要各位肯定闪存管理了。应运用于 cgo 中都假设的API中都可能才会来到 *C.char,它实质上是 C 侧重上开辟的一段闪存空间,并不需要被显式被囚。例如,libterraform.go中都假设了启动时 Terraform 可用参考资料的新方法 ConfigLoadConfigDir,其假定如下:

//export ConfigLoadConfigDirfuncConfigLoadConfigDir(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)returncMod, cDiags, cError}diagsBytes, err := json.Marshal(diags)iferr != 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才会在 C 侧重上申商量了一段闪存空间,并来到结果来到给多线程者,那么多线程者(Python 假定)并不需要在应运用于下回来到值便显式被囚闪存。

在此以后,并不需要先通过 cgo 去除被囚闪存的新方法:

//export FreefuncFree(cString *int){C.free(unsafe.Pointer(cString))}

然后,在 Python 中都就可以假定如下积体电路:

importosfromctypes importcdll, c_void_pfromlibterraform.common importWINDOWS

classLoadConfigDirResult(Structure):_fields_ = [("r0", c_void_p),("r1", c_void_p),("r2", c_void_p)]

_load_config_dir = _lib_tf.ConfigLoadConfigDir_load_config_dir.argtypes = [c_char_p]_load_config_dir.restype = LoadConfigDirResult

root = os.path.dirname(os.path.abspath(词组file词组))_lib_filename = 'libterraform.dll'ifWINDOWS else'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)来显式被囚闪存,从而可避免闪存截获。

▌陨 3:捉到输入

在 Terraform 的OpenBSD中都,分派立即的输入才会扫描到标准规范输入 stdout和标准规范偏差输入 stderr上,那么应运用于 cgo 积体电路出新 RunCli的API,并被 Python 多线程时,预设情况下就这样一来输入到 stdout和 stderr上了。

这才会有什么疑问呢?如果同时分派两个立即,输入结果才会交错,没区分这些结果是哪个立即的结果。

克服思路就是应运用于水管:

在 Python 假定中都应运用于 os.pipe 分别始创运用于标准规范输入和标准规范偏差输入的水管(才会作用于机密文件POD) 将两个机密文件POD传入到 libterraform.go 的 RunCli 新方法中都,在本体应运用于 os.NewFile 打开两个机密文件POD,并分别替换 os.Stdout 和 os.Stderr 在 RunCli 新方法结束时关闭这两个机密文件,并恢复完整的 os.Stdout 和 os.Stderr

此外,应运用于 os.pipe给与到的机密文件POD给 libterraform.go应运用于时要肯定可用系统的不同:

对于 Linux/Unix 来说,这样一来传进去应运用于需 对于 Windows 来说,并不需要额外将机密文件POD转换成机密文件实例,这是因为在 Windows 上 GoLang 的 os.NewFile 交还的是机密文件实例

Python 中都具体标识符如下:

ifWINDOWS: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_stderr_fd)

▌陨 4:水管 Hang

由于水管的大小有容许,如果擦除高达了容许就才会导致写到 Hang。因此不能在多线程 RunCli(即才会把立即输入擦除水管)便去水管中都加载输入,否则才会推测在分派直观立即(如version)时正常,在分派复杂立即(如apply,因为有大量输入)时才会 Hang 长住。

克服思路就是在多线程 RunCli前就启动两个多线程分别加载标准规范输入和标准规范偏差输入的机密文件POD内容,在多线程 RunCli立即便去 join这两个多线程。Python 中都具体标识符如下:

r_stdout_fd,w_stdout_fd = os.piper_stderr_fd,w_stderr_fd = os.pipe

stdout_buffer= []stderr_buffer= []stdout_thread= Thread(target=cls._fdread, args=(r_stdout_fd, stdout_buffer))stdout_thread.daemon= Truestdout_thread.startstderr_thread= Thread(target=cls._fdread, args=(r_stderr_fd, stderr_buffer))stderr_thread.daemon= Truestderr_thread.start

ifWINDOWS: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_stderr_fd)

stdout_thread.joinstderr_thread.joinifnot stdout_buffer:raiseTerraformFdReadError(fd=r_stdout_fd)ifnot stderr_buffer:raiseTerraformFdReadError(fd=r_stderr_fd)stdout= stdout_buffer[0]stderr= stderr_buffer[0]

概述

当推测现有的自由软件坎保证不了需求时,手撸了 py-libterraform,基本假定了在单假定中都多线程 Terraform 立即的要求。尽管在开发设计流程中都遇到了各种疑问,并并不需要迅速在 Python、GoLang、C 两者之间跳转,但好在一个个克服了,历史纪录此流程若能让大家少“踩陨”也算值啦!

简介

python-terraform: py-libterraform:

苹果公司最MVP技术人员(MVP)

苹果公司最MVP技术人员是苹果公司公司授予第三方系统设计专业人士的一个亚洲地区获奖者。29年来,亚洲地区的系统设计邻里领袖人物,因其在线上和比方说的系统设计邻里中都体才会经验和经验而获此获奖者。

MVP是经过严格挑选的技术人员工作团队,他们代表着系统设计最超群且最具与生俱来的人,是对邻里投入极大的勇气并心地善良的技术人员。MVP专注通过讲话、论坛解说、始创的网站、编撰其网站、体才会录像带、自由软件这两项、组织代表大才会等方式则来试图他人,并最大侧重地试图苹果公司系统设计邻里服务器应运用于 Microsoft 系统设计。

更多附注登录官方的网站:

谢谢你念书了本文!欢迎在评论区部落格体才会你的或许,并且发信到博文。

如果你对本文青睐有加,决心发表文章到自己的平台,商量在前台澄清「发表文章」与我们取得联系!

非议苹果公司中都国MSDN

加入苹果公司MVP

河南白癜风医院哪里比较好
苏州看白癜风的专业医院
艾拉莫德片适用哪些人群
河北白癜风挂号
信阳好的妇科专科医院
卫生间的小飞虫到底是啥?别看外表奇怪的是,但它的危害超出你想象

拍戏死一个又来两个,有点不胜其烦。 那它们又在在哪冒出来的? 小小肌肉的天牛蚯蚓有一个响亮的名号—“矿坑侦探”。 可以说是,天牛蚯...

友情链接