自動(dòng)生成Cloudflare的Terraform Provider

來(lái)源:Cloudflare
作者:Cloudflare
時(shí)間:2024-11-02
2360
2022年11月,我們宣布了Cloudflare API過(guò)渡到OpenAPI模式。當(dāng)時(shí),我們有一個(gè)大膽的目標(biāo),就是使OpenAPI模式成為我們SDK生態(tài)系統(tǒng)和參考文檔的真實(shí)來(lái)源。

78BFFC10-9560-4535-B7B2-5179E47B343E.jpeg

2022年11月,我們宣布了Cloudflare API過(guò)渡到OpenAPI模式。當(dāng)時(shí),我們有一個(gè)大膽的目標(biāo),就是使OpenAPI模式成為我們SDK生態(tài)系統(tǒng)和參考文檔的真實(shí)來(lái)源。為此,在2024年的Developer Week期間,我們宣布:我們的SDK庫(kù)現(xiàn)在從這些OpenAPI模式自動(dòng)生成。今天,我們隆重宣布,該生態(tài)系統(tǒng)的最新組成部分現(xiàn)將自動(dòng)生成——Terraform provider和API參考文檔。

這意味著,一旦我們的產(chǎn)品中添加新的功能或?qū)傩?,并由團(tuán)隊(duì)記錄到文檔,您將能看到它在我們的SDK生態(tài)系統(tǒng)應(yīng)當(dāng)如何使用,并能立即投入使用。不再存在延誤。不再遺漏API端點(diǎn)。點(diǎn)擊https://developers.cloudflare.com/api-next/查看新文檔站點(diǎn),您可以通過(guò)安裝5.0.0-alpha1來(lái)嘗試Terraform提供者的預(yù)覽發(fā)布候選版。

為什么使用Terraform?

對(duì)于不熟悉Terraform的人來(lái)說(shuō),它是一個(gè)用于以代碼形式管理基礎(chǔ)設(shè)施的工具,就像管理應(yīng)用代碼一樣。我們的許多客戶(無(wú)論大?。┒家蕾嘥erraform以技術(shù)無(wú)關(guān)的方式協(xié)調(diào)他們的基礎(chǔ)設(shè)施。從本質(zhì)上講,它是一個(gè)具備生命周期管理的HTTP客戶端,這意味著它利用我們公開文檔化的API,以理解如何在資源的整個(gè)生命周期內(nèi)進(jìn)行創(chuàng)建、讀取、更新和刪除操作。

保持Terraform更新——老方法

在過(guò)去,Cloudflare一直手動(dòng)維護(hù)Terraform provider,但由于該provider的內(nèi)部結(jié)構(gòu)需要自己獨(dú)特的操作方式,維護(hù)和支持的責(zé)任落在了少數(shù)人的肩上。服務(wù)團(tuán)隊(duì)總是難以跟上更改的數(shù)量,因?yàn)樵趐rovider中進(jìn)行一個(gè)更改都需要大量的認(rèn)知開銷。一個(gè)團(tuán)隊(duì)要更改provider,至少需要3個(gè)拉取請(qǐng)求(如果您要添加對(duì)cf-terraforming的支持,則需要4個(gè)請(qǐng)求)。

BFA2F90F-9084-4B0C-A323-62EAC143B043.jpeg

即使在4個(gè)拉取請(qǐng)求完成后,也不能保證覆蓋所有可用屬性,這意味著可能會(huì)忘記小而重要的細(xì)節(jié)且沒有暴露給客戶,導(dǎo)致在嘗試配置資源時(shí)受挫。為了解決這個(gè)問(wèn)題,我們的Terraform provider需要依賴于同我們的SDK生態(tài)系統(tǒng)已經(jīng)從中受益的其他部的相同的OpenAPI模式。

自動(dòng)更新Terraform

Terraform與我們的SDK的不同之處在于,它管理資源的生命周期。隨之而來(lái)的是與已知值以及管理請(qǐng)求和響應(yīng)有效負(fù)載中的差異相關(guān)的一系列新問(wèn)題。我們來(lái)比較一下創(chuàng)建新DNS記錄并將其取回的兩種不同方法。

使用我們的Go SDK:

A7DF920C-2D77-44FD-92CF-36FAB76BCE36.jpeg

使用Terraform時(shí):

1AFFC488-186C-45FD-A3CF-835A7676CCEB.jpeg

表面上看,Terraform方法更簡(jiǎn)單,您是對(duì)的。我們已為您處理了了解如何創(chuàng)建新資源和維護(hù)更改的復(fù)雜性。但問(wèn)題在于,為了讓Terraform提供這種抽象和數(shù)據(jù)保證,在應(yīng)用時(shí)必須知道所有值。這意味著,即使您沒有使用代理值value,Terraform也需要知道這個(gè)值需要是什么,以便將其保存在狀態(tài)文件中,并在日后管理該屬性。以下錯(cuò)誤是Terraform操作人員在應(yīng)用值未知時(shí),通常會(huì)從provider那里看到的錯(cuò)誤。

CA642083-EF1B-4F65-BF83-66A3413E7EF7.jpeg

而在使用SDK時(shí),如果您不需要某個(gè)字段,則可以忽略它,永遠(yuǎn)不需要擔(dān)心維護(hù)已知值。

為我們的OpenAPI模式解決這個(gè)問(wèn)題不是易事。自從引入Terraform生成支持以來(lái),我們模式的質(zhì)量已經(jīng)提高了一個(gè)數(shù)量級(jí)?,F(xiàn)在,我們顯式地調(diào)用所有存在的默認(rèn)值,基于請(qǐng)求有效負(fù)載的變量響應(yīng)屬性,以及任何服務(wù)器端計(jì)算的屬性。這一切都意味著為與我們API交互的任何人提供更好的體驗(yàn)。

從terraform-plugin-sdk遷移到terraform-plugin-framework

要構(gòu)建Terraform provider并向操作人員公開資源或數(shù)據(jù)源,您需要兩個(gè)主要因素:一個(gè)provider服務(wù)器和一個(gè)provider。

Provider服務(wù)器負(fù)責(zé)暴露一個(gè)gRPC服務(wù)器,Terraform核心(通過(guò)CLI)使用該服務(wù)器在管理資源或從操作人員提供的配置中讀取數(shù)據(jù)源時(shí)使用該服務(wù)器進(jìn)行通信。

Provider負(fù)責(zé)包裝資源和數(shù)據(jù)源,與遠(yuǎn)程服務(wù)通信,并管理狀態(tài)文件。為此,您可以依賴terraform-plugin-sdk(通常稱為SDKv2)或terraform-plugin-framework,其中包括Terraform提供的所有接口和方法,以便正確管理其內(nèi)部機(jī)制。使用哪一個(gè)插件取決于provider的存在時(shí)間。SDKv2存在的時(shí)間更長(zhǎng),大多數(shù)Terraform provider都使用它,但由于時(shí)間長(zhǎng)和復(fù)雜性,它有許多核心未解決的問(wèn)題必須

保留,以便為依賴它的客戶提供向后兼容性。terraform-plugin-framework是新版本,雖然缺乏SDKv2的功能廣度,但提供了一種更像Go的方法來(lái)構(gòu)建provider,并解決了SDKv2中的許多底層錯(cuò)誤。

Cloudflare Terraform provider的大部分內(nèi)容都是使用SDKv2構(gòu)建的,但在2023年初,我們采用了多路復(fù)用方式,在我們的provider中同時(shí)提供兩者。要理解為什么需要這樣做,我們必須對(duì)SDKv2有所了解。SDKv2的組織方式并不利于一致且可靠地表示null或“未設(shè)置”的值。您可以使用實(shí)驗(yàn)性的ResourceData.GetRawConfig來(lái)檢查配置中是否已設(shè)置值、為null或未知,但實(shí)際上并不支持將其寫回為null。我們首次發(fā)現(xiàn)這個(gè)限制是在邊緣規(guī)則引擎(規(guī)則集)開始引入新服務(wù)的時(shí)候,這些服務(wù)需要支持的API響應(yīng)中包含未設(shè)置(或缺失)、true或false狀態(tài)的布爾值,每個(gè)狀態(tài)都有自己的原因和目的。雖然這不是Cloudflare的常規(guī)API設(shè)計(jì),但它是一種合法的方式,我們應(yīng)該能夠處理。但是,如上所述,SDKv2 provider不能處理。這是因?yàn)?,?dāng)一個(gè)值沒有出現(xiàn)在響應(yīng)中或讀入狀態(tài)時(shí),它會(huì)獲得一個(gè)與Go兼容的零值作為默認(rèn)值。表現(xiàn)為在寫入狀態(tài)為假值后無(wú)法取消設(shè)置值(反之亦然)。

要可靠地使用這些布爾值的三個(gè)狀態(tài),我們擁有的唯一解決方案是遷移到terraform-plugin-framework,該框架具有寫回未設(shè)置值的正確實(shí)現(xiàn)。

在我們開始在老版provider中使用terraform-plugin-framework添加更多功能后,開發(fā)人員體驗(yàn)顯然得到了改善,因此我們添加了一個(gè)限制,以防止未來(lái)任何人繼續(xù)使用SDKv2并無(wú)意中讓自己陷入這個(gè)問(wèn)題。當(dāng)我們決定將自動(dòng)生成Terraform provider時(shí),最理想的做法是將所有資源都基于terraform-plugin-framework,并徹底擺脫SDKv2中的問(wèn)題。這確實(shí)使遷移復(fù)雜化了,因?yàn)閮?nèi)部結(jié)構(gòu)改進(jìn)后,主要組件也發(fā)生了變化,例如我們需要熟悉的模式和CRUD操作。但是,這是一項(xiàng)值得的投資,因?yàn)橥ㄟ^(guò)這樣做,我們已經(jīng)為provider的基礎(chǔ)做好了面向未來(lái)的準(zhǔn)備,并減少了因存在缺陷的遺留內(nèi)部機(jī)制而導(dǎo)致的妥協(xié),以提供優(yōu)秀的Terraform體驗(yàn)。

以迭代方式發(fā)現(xiàn)缺陷

代碼生成管道常見的一個(gè)問(wèn)題是,除非您有現(xiàn)成的工具來(lái)實(shí)現(xiàn)你的新產(chǎn)品,否則很難判斷它是否有效或是否值得使用。當(dāng)然,您也可以生成測(cè)試來(lái)演練新產(chǎn)品,但如果管道中存在錯(cuò)誤,您可能很難發(fā)現(xiàn)一些缺陷-因?yàn)槟傻臏y(cè)試結(jié)果會(huì)將這個(gè)缺陷顯示為預(yù)期內(nèi)的行為。

我們已有的一個(gè)重要反饋回路就是現(xiàn)有的驗(yàn)收測(cè)試套件。對(duì)現(xiàn)有provider中的所有資源進(jìn)行回歸和功能測(cè)試。最棒的一點(diǎn)是,由于測(cè)試套件正在創(chuàng)建和管理真實(shí)資源,我們只需查看HTTP流量,看看API調(diào)用是否被遠(yuǎn)程端點(diǎn)接受,就能很容易判斷結(jié)果是否是一個(gè)有效的實(shí)現(xiàn)。移植測(cè)試套件只需復(fù)制所有現(xiàn)有的測(cè)試,并檢查任何類型斷言的差異(例如列表到單個(gè)嵌套列表),然后啟動(dòng)測(cè)試運(yùn)行以確定資源是否正常工作。

雖然集中式模式管道顯著提高了效率,模式修復(fù)幾乎瞬間即可傳播到整個(gè)生態(tài)系統(tǒng),但它無(wú)法幫助我們解決最大的障礙,即揭露隱藏其他缺陷的缺陷。這非常耗時(shí),因?yàn)樾迯?fù)Terraform中的問(wèn)題時(shí),有三個(gè)地方可能遇到錯(cuò)誤:

1.在進(jìn)行任何API調(diào)用之前,Terraform會(huì)實(shí)施邏輯模式驗(yàn)證,當(dāng)遇到驗(yàn)證錯(cuò)誤時(shí),它將立即停止。

2.如果任何API調(diào)用失敗,它會(huì)在CRUD操作處停止并返回診斷信息,并立即停止。

3.在CRUD操作運(yùn)行后,Terraform會(huì)進(jìn)行檢查,以確保所有的值都是已知的。

這意味著,如果我們?cè)诘谝徊接龅饺毕?,然后予以修?fù),不能保證或無(wú)法知道是否還有另外兩個(gè)錯(cuò)誤在等著我們。更不用說(shuō),如果我們?cè)诘?步中發(fā)現(xiàn)了一個(gè)錯(cuò)誤并發(fā)布了修復(fù),就一定能確保不會(huì)在下一輪測(cè)試中的第1步發(fā)現(xiàn)錯(cuò)誤了。

對(duì)此沒有靈丹妙藥,我們的解決辦法是注意模式行為中的有問(wèn)題模式,并在它進(jìn)入代碼生成管道之前,在OpenAPI架構(gòu)中應(yīng)用CI lint規(guī)則。采用這種方法逐步減少第1步和第2步的錯(cuò)誤數(shù)量,直到基本上只要處理第3步中的錯(cuò)誤類型。

可重用性更高的模型和結(jié)構(gòu)體轉(zhuǎn)換方法

在Terraform provider的CRUD操作中,相當(dāng)常見的樣板文件如下:

48FD989F-1EF9-451E-B2BA-F98276291D9B.jpeg

總體而言:

-我們使用req.Plan.Get()獲取建議的更新(稱為計(jì)劃)

-執(zhí)行使用新值的更新API調(diào)用

-將數(shù)據(jù)從Go類型轉(zhuǎn)換為Terraform模型(convertResponseToThingModel)

-調(diào)用resp.State.Set()來(lái)設(shè)置狀態(tài)

最初,這似乎沒有太大問(wèn)題。然而,第3步將Go類型轉(zhuǎn)換為Terraform模型時(shí),很快就會(huì)變得繁瑣、容易出錯(cuò)且復(fù)雜,因?yàn)樗匈Y源都需要這樣做才能在類型和相關(guān)的Terraform模型之間切換。為了避免生成比必要更復(fù)雜的代碼,我們的provider中進(jìn)行的一項(xiàng)改進(jìn)是,所有CRUD方法使用統(tǒng)一的apijson.Marshal、apijson.Unmarshal和apijson.UnmarshalComp方法,這些方法通過(guò)基于結(jié)構(gòu)體標(biāo)簽集中轉(zhuǎn)換和處理邏輯來(lái)解決這個(gè)問(wèn)題。

296A6721-145F-4F11-A15C-8B833ECE02B3.jpeg

我們不需要生成數(shù)百個(gè)類型到模型轉(zhuǎn)換方法的實(shí)例,而是給Terraform模型添加正確的標(biāo)簽,以一致的方式處理數(shù)據(jù)的序列化和反序列化。這只是對(duì)代碼的一個(gè)小改動(dòng),但從長(zhǎng)遠(yuǎn)來(lái)看,卻使生成的代碼更具可重用性和可讀性。這種方法的另一個(gè)好處是,它非常適合錯(cuò)誤修復(fù),因?yàn)橐坏┠R(shí)別出特定類型字段的錯(cuò)誤,只要在統(tǒng)一界面中修復(fù)該錯(cuò)誤,就能解決其他您可能還沒有發(fā)現(xiàn)的錯(cuò)誤。

更多(文檔)持續(xù)更新中

為了提升我們的OpenAPI模式使用,我們正在加強(qiáng)SDK與新API文檔站點(diǎn)的集成。它使用了我們過(guò)去兩年投資并解決了一些常見使用問(wèn)題的相同管道。

SDK感知

如果您使用過(guò)我們的API文檔站點(diǎn),您就知道我們提供使用curl等命令行工具與API交互的示例。這是一個(gè)很好的起點(diǎn),但如果您使用的是其中一個(gè)SDK庫(kù),您需要設(shè)法將其轉(zhuǎn)換為您想要使用的方法或類型定義?,F(xiàn)在我們使用相同的管道來(lái)生成SDK和文檔,我們將通過(guò)提供您可能使用的所有庫(kù)中的示例來(lái)解決這個(gè)問(wèn)題,而不限于curl。

E0752410-44FD-44AC-9598-611F32745CA3.jpeg

使用cURL獲取所有區(qū)域的示例。

7BFF1E2F-31CB-4436-B350-F29ECE5358AB.jpeg

使用Typescript庫(kù)獲取所有區(qū)域的示例。

663AA2C1-C588-4CCB-B977-0BB51E9379D7.jpeg

使用Python庫(kù)獲取所有區(qū)域的示例。

16F63EB7-D5B2-4474-964B-E67990775939.jpeg

使用Go庫(kù)獲取所有區(qū)域的示例。

通過(guò)這一改進(jìn),我們還可以記住語(yǔ)言選擇,因此,如果您選擇使用Typescript庫(kù)查看文檔并繼續(xù)瀏覽,我們將一直向您顯示使用Typescript的示例,直至更換到其他語(yǔ)言。

最棒的是,當(dāng)我們向現(xiàn)有端點(diǎn)引入新屬性或添加SDK語(yǔ)言時(shí),這個(gè)文檔站點(diǎn)會(huì)自動(dòng)與管道保持同步。使其保持最新不再需要付出巨大的工作量。

渲染更快、更高效

我們一直難以解決的一個(gè)問(wèn)題是API端點(diǎn)的龐大數(shù)量以及如何表示它們。截至本文,我們有1,330個(gè)端點(diǎn),對(duì)于每個(gè)端點(diǎn),我們有一個(gè)請(qǐng)求有效負(fù)載,一個(gè)響應(yīng)有效負(fù)載,以及多個(gè)關(guān)聯(lián)的類型。在渲染這么多信息時(shí),我們過(guò)去使用的解決方案不得不做出一些權(quán)衡,以便讓部分表示能夠正常工作。

API文檔站點(diǎn)的下一個(gè)迭代通過(guò)幾種方式解決了這個(gè)問(wèn)題:

-它被實(shí)施為一個(gè)現(xiàn)代React應(yīng)用,將交互式客戶端體驗(yàn)與靜態(tài)預(yù)渲染內(nèi)容結(jié)合起來(lái),從而實(shí)現(xiàn)快速初始加載和快捷導(dǎo)航。(是的,即使不啟用JavaScript,它也能正常工作?。?。

-它會(huì)隨著您瀏覽時(shí)逐步獲取底層數(shù)據(jù)。

通過(guò)解決這個(gè)基本問(wèn)題,我們還解鎖了對(duì)文檔站點(diǎn)和SDK生態(tài)系統(tǒng)的其他計(jì)劃改進(jìn),以提升用戶體驗(yàn),而不再需要像過(guò)去那樣做出權(quán)衡。

權(quán)限

在文檔網(wǎng)站中,用戶最希望重新實(shí)現(xiàn)的功能之一就是API端點(diǎn)的最低所需權(quán)限。文檔網(wǎng)站的早期版本中曾經(jīng)提供這個(gè)功能。然而,大多數(shù)使用它的人并不知道,這些值是手動(dòng)維護(hù)的,且經(jīng)常不正確,導(dǎo)致用戶提交支持工單并感到沮喪。

在Cloudflare的身份和訪問(wèn)管理系統(tǒng)中,“我需要什么才能訪問(wèn)這個(gè)端點(diǎn)”并不是一個(gè)簡(jiǎn)單的問(wèn)題。這樣做的原因是,在請(qǐng)求發(fā)送到控制平面的正常流程中,我們需要兩個(gè)不同的系統(tǒng)來(lái)回答問(wèn)題的一部分,然后將這些信息結(jié)合起來(lái)給出完整的答案。由于我們最初無(wú)法作為OpenAPI管道的一部分自動(dòng)執(zhí)行此操作,因此我們選擇將其排除在外,而不是提供一個(gè)錯(cuò)誤且無(wú)法驗(yàn)證的值。

快進(jìn)到今天,我們很高興地宣布,端點(diǎn)權(quán)限已經(jīng)回來(lái)了!我們構(gòu)建了一些新的工具,以抽象的方式回答這個(gè)問(wèn)題,讓我們可以將其集成到代碼生成管道中,并讓所有端點(diǎn)自動(dòng)獲取這些信息。與代碼生成平臺(tái)的其他部分非常類似,它專注于讓服務(wù)團(tuán)隊(duì)擁有并維護(hù)高質(zhì)量的模式,可供重復(fù)使用并增加價(jià)值,無(wú)需他們進(jìn)行任何工作。

C29C053B-B779-4DB2-86D9-D801BC73CC54.jpeg

無(wú)需再等待更新

隨著這一系列更新的發(fā)布,我們將不再需要等待更新才能進(jìn)入SDK生態(tài)系統(tǒng)。通過(guò)這些新的改進(jìn),我們能夠在團(tuán)隊(duì)記錄新屬性和端點(diǎn)時(shí)立即優(yōu)化它們的能力。

立即登錄,閱讀全文
原文鏈接:點(diǎn)擊前往 >
文章來(lái)源:Cloudflare
版權(quán)說(shuō)明:本文內(nèi)容來(lái)自于Cloudflare,本站不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。文章內(nèi)容系作者個(gè)人觀點(diǎn),不代表快出海對(duì)觀點(diǎn)贊同或支持。如有侵權(quán),請(qǐng)聯(lián)系管理員(zzx@kchuhai.com)刪除!
相關(guān)文章
【科普篇】什么是機(jī)器人管理?| 機(jī)器人管理器如何運(yùn)作
【科普篇】什么是機(jī)器人管理?| 機(jī)器人管理器如何運(yùn)作
機(jī)器人管理是指,阻止有害或惡意的互聯(lián)網(wǎng)機(jī)器人流量,同時(shí)仍允許有用的機(jī)器人訪問(wèn) web 資產(chǎn)。為此,機(jī)器人管理檢測(cè)機(jī)器人活動(dòng)、辨別有用和有害的機(jī)器人行為,并識(shí)別有害活動(dòng)的來(lái)源。
Cloudflare
云服務(wù)
2024-12-29
【科普篇】云防火墻及防火墻即服務(wù)(FWaaS)
【科普篇】云防火墻及防火墻即服務(wù)(FWaaS)
云防火墻是一種安全產(chǎn)品,與傳統(tǒng)防火墻一樣,可以過(guò)濾掉潛在的惡意網(wǎng)絡(luò)流量。而與傳統(tǒng)防火墻不同的是,云防火墻托管在云中。這種防火墻的云交付模式也稱為防火墻即服務(wù) (FWaaS)。
Cloudflare
云服務(wù)
2024-12-29
【科普篇】如何預(yù)防網(wǎng)絡(luò)釣魚
【科普篇】如何預(yù)防網(wǎng)絡(luò)釣魚
網(wǎng)絡(luò)釣魚是一種網(wǎng)絡(luò)攻擊,攻擊者隱藏自己的真實(shí)身份,以欺騙受害者完成其所期望的操作。
Cloudflare
云服務(wù)
2024-12-23
【科普篇】如何阻止垃圾電子郵件
【科普篇】如何阻止垃圾電子郵件
垃圾郵件是“不請(qǐng)自來(lái)”的電子郵件,通常是批量發(fā)送的。雖然某些垃圾郵件是推銷性質(zhì)的,并沒有明顯的惡意,但它們也可用于各種攻擊。
Cloudflare
云服務(wù)
2024-12-23
優(yōu)質(zhì)服務(wù)商推薦
更多
掃碼登錄
打開掃一掃, 關(guān)注公眾號(hào)后即可登錄/注冊(cè)
加載中
二維碼已失效 請(qǐng)重試
刷新
賬號(hào)登錄/注冊(cè)
小程序
快出海小程序
公眾號(hào)
快出海公眾號(hào)
商務(wù)合作
商務(wù)合作
投稿采訪
投稿采訪
出海管家
出海管家