KubeVela:100行のコードでAWSの最も人気のある50のクラウドリソースをすばやく紹介する方法

著者:KubeVelaコミュニティ

KubeVelaは現在、AWS、Azure、GCP、Alibaba Cloud、Tencent Cloud、Baidu Cloud、UCloudなどのクラウドベンダーをサポートしており、クラウドサービスプロバイダーからのクラウドリソースを導入するためのシンプルで迅速なコマンドラインツール[1]も提供していますが、KubeVelaでは1クラウドサービスプロバイダーのクラウドリソースをサポートするだけでは、クラウドリソースに対するユーザーのニーズにすばやく対応することはできません。この記事では、100行未満のコードでAWSで最も人気のあるクラウドリソースのトップ50をすばやく紹介するソリューションを提供します。

同時に、ユーザーがこの記事に触発され、他のクラウドサービスプロバイダーからのクラウドリソースを提供することも期待しています。

AWSで最も人気のあるクラウドリソースはどこにありますか?

Terraformの公式ウェブサイトは、AWSのクラウドリソースTerraformモジュール[2]など、さまざまなクラウドサービスプロバイダーのTerraformモジュールを提供しています。その中で、クラウドリソースは人気(ダウンロード)で並べ替えられます。たとえば、AWSVPCのダウンロード数は1870万です。

簡単な分析により、AWSトップ50のTerraformモジュールのデータは、 registry.terraform.io / v2 / modules?…をリクエストすることで取得できることがわかりました

開始前

このコードは、ユーザーから渡された2つのパラメーターを受け入れます。•プロバイダーの名前•プロバイダーに対応するTerraformモジュールのURL

AWSの場合、プロバイダー名は「aws」であり、対応するTerraformモジュールはTerraform Modules jsonフォーマットインターフェース[3]です(つまり、プロバイダーがawsの場合に最も人気のある50のクラウドリソースをTerraformレジストリ[4]で検索します) 。コードを実行する前に、providerName(aws)とModulesのリンクが正しいことを確認する必要があります。

コードを実行する

次に、次の100行ほどのコード(ファイル名gen.go)を使用して、最も人気のある上位50のAWSクラウドリソースをバッチですばやく紹介できます。

import (
  "encoding/json"
  "fmt"
  "io"
  "log"
  "net/http"
  "os"
  "os/exec"
  "path/filepath"
  "strings"
  "github.com/pkg/errors"
)
type TFDownload struct {
  Data     []DataItem     `json:"data"`
  Included []IncludedItem `json:"included"`
}
type IncludedItem struct {
  Id         string     `json:"id"`
  Attributes Attributes `json:"attributes"`
}
type DataItem struct {
  Attributes    Attributes    `json:"attributes"`
  Relationships Relationships `json:"relationships"`
}
type Relationships struct {
  LatestVersion RelationshipLatestVersion `json:"latest-version"`
}
type RelationshipLatestVersion struct {
  Data RelationshipData `json:"data"`
}
type RelationshipData struct {
  Id string `json:"id"`
}
var errNoVariables = errors.New("failed to find main.tf or variables.tf in Terraform configurations")
type Attributes struct {
  Name        string `json:"name"`
  Downloads   int    `json:"downloads"`
  Source      string `json:"source"`
  Description string `json:"description"`
  Verified    bool   `json:"verified"`
}
func main() {
  if len(os.Args) < 2 {
     fmt.Println("Please provide the cloud provider name and an official Terraform modules URL")
     os.Exit(1)
  }
  providerName := os.Args[1]
  terraformModulesUrl := os.Args[2]
  resp, err := http.Get(terraformModulesUrl)
  if err != nil {
     log.Fatal(err)
  }
  defer resp.Body.Close()
  body, err := io.ReadAll(resp.Body)
  if err != nil {
     log.Fatal(err)
  }
  var modules TFDownload
  if err := json.Unmarshal(body, &modules); err != nil {
     fmt.Println(err.Error())
     os.Exit(1)
  }
  if _, err = os.Stat(providerName); err == nil {
     if err := os.RemoveAll(providerName); err != nil {
        log.Fatal(err)
     }
     fmt.Printf("Successfully deleted existed directory %s\n", providerName)
  }
  if _, err = os.Stat(providerName); os.IsNotExist(err) {
     if err := os.Mkdir(providerName, 0755); err != nil {
        if !os.IsExist(err) {
           log.Fatal(err)
        }
        fmt.Printf("Successfully created directory %s\n", providerName)
     }
  }
  for _, module := range modules.Data {
     var description string
     for _, attr := range modules.Included {
        if module.Relationships.LatestVersion.Data.Id == attr.Id {
           description = attr.Attributes.Description
        }
     }
     if description == "" {
        description = strings.ToUpper(providerName) + " " + strings.Title(module.Attributes.Name)
     }
     outputFile := fmt.Sprintf("%s/terraform-%s-%s.yaml", providerName, providerName, module.Attributes.Name)
     if _, err := os.Stat(outputFile); !os.IsNotExist(err) {
        continue
     }
     if providerName == "aws" && (module.Attributes.Name == "rds" || module.Attributes.Name == "s3-bucket" ||
        module.Attributes.Name == "subnet" || module.Attributes.Name == "vpc") {
        continue
     }
     if err := generateDefinition(providerName, module.Attributes.Name, module.Attributes.Source, "", description); err != nil {
        fmt.Println(err.Error())
        os.Exit(1)
     }
  }
}
func generateDefinition(provider, name, gitURL, path, description string) error {
  defYaml := filepath.Join(provider, fmt.Sprintf("terraform-%s-%s.yaml", provider, name))
  cmd := fmt.Sprintf("vela def init %s --type component --provider %s --git %s.git --desc \"%s\" -o %s",
     name, provider, gitURL, description, defYaml)
  if path != "" {
     cmd = fmt.Sprintf("%s --path %s", cmd, path)
  }
  fmt.Println(cmd)
  stdout, err := exec.Command("bash", "-c", cmd).CombinedOutput()
  if err != nil {
     return errors.Wrap(err, string(stdout))
  }
  fmt.Println(string(stdout))
  return nil
复制代码

注文の実行:

go run gen.go aws "https://registry.terraform.io/v2/modules?filter%5Bprovider%5D=aws&include=latest-version&page%5Bsize%5D=50&page%5Bnumber%5D=1"
复制代码

コード簡単な説明

解析云资源数据

访问用户传入的 URL,将返回的 json 数据解析为 Go 中的结构体。

资源对应的 json 格式如下:

{
  "data": [
    {
      "type": "modules",
      "id": "23",
      "attributes": {
        "downloads": 18440513,
        "full-name": "terraform-aws-modules/vpc/aws",
        "name": "vpc",
        "namespace": "terraform-aws-modules",
        "owner-name": "",
        "provider-logo-url": "/images/providers/aws.png",
        "provider-name": "aws",
        "source": "https://github.com/terraform-aws-modules/terraform-aws-vpc",
        "verified": true
      },
      "relationships": {
        "latest-version": {
          "data": {
            "id": "142143",
            "type": "module-versions"
          }
        }
      },
      "links": {
        "self": "/v2/modules/23"
      }
    },
    ...
  ],
  "included": [
    {
      "type": "module-versions",
      "id": "36806",
      "attributes": {
        "created-at": "2020-01-03T11:35:36Z",
        "description": "Terraform module Terraform module for creating AWS IAM Roles with heredocs",
        "downloads": 260030,
        "published-at": "2020-02-06T06:26:08Z",
        "source": "",
        "tag": "v2.0.0",
        "updated-at": "2022-02-22T00:45:44Z",
        "version": "2.0.0"
      },
      "links": {
        "self": "/v2/module-versions/36806"
      }
    },
    ...
  ],
  ...
}
复制代码

在 Modules 对应的 json 数据中,我们只关心两个键值对,即:

• data:包含 Modules 名称及属性的列表 • Included:筛选出的特定版本的 Modules 具体信息

其中,对于 data 中的每个 Module 元素,解析它的属性,Id 和 relationship 中的 latest-version 对应的 id;对于 Included 中的每个 Module 版本元素,解析它的属性和Id。

属性又解析如下五项:

• Name • Downloads • Source • Description • Verified

结构体定义在结构体 TFDownload 中,通过 http 库获取 json 数据,再通过 json.Unmarshal 解析出 Terraform modules 的结构体。

批量生产云资源

1. 新建目录,生成资源所需文件

解析完毕后,在当前目录下新建文件夹,文件夹命名为 provider 名称。 遍历解析后的 data,对于其中每个 Module 元素,执行下述操作,为其生成相应配置文件,定义和相应文档。

2. 生成定义文件

通过下述 vela 指令从模块对应的 github 仓库读取相应信息生成定义文件。

vela def init {ModuleName} --type component --provider {providerName} --git {gitURL} --desc {description} -o {yamlFileName}
复制代码

指令中需要填入的几项由解析好的 Module 结构体传入。

• gitURL: {Module.Attributes.Source}.git

• description: 如果 Included 中存在元素 ID 与模块 relationship 中 latest-version 对应 ID 相同,则 description 为 Included 中对应元素属性的 description;否则 description 为 providerName 与模块名称的拼接

•yamlFileName:terraform-{providerName}-{Module.Attributes.Name} .yaml

あなたもやってみますか?

豊富なTerraformモジュールを提供する多くのクラウドサービスプロバイダーもあります。

GCP:registry.terraform.io/namespaces/…

Alibaba Cloud:registry.terraform.io/namespaces/…

使用している、または気に入っているクラウドサービスプロバイダーのクラウドリソースもKubeVelaに紹介しますか?

関連リンク

[1]シンプルで高速なコマンドラインツール

kubevela.io/docs/next/p…

[2]AWSのクラウドリソースTerraformモジュール

Registry.terraform.io/namespaces/…

[3]Terraformモジュールのjson形式のインターフェース

Registry.terraform.io/v2/modules?…

[4]Terraformレジストリ

aregistry.terraform.io/

おすすめ

転載: juejin.im/post/7078187427088564255