Fix: support generate Terraform ComponentDefinition from local HCL file

Besides generating a Terraform ComponentDefinition from a remote git repo,
support generate one from local HCL file

Signed-off-by: Zheng Xi Zhou <zzxwill@gmail.com>
This commit is contained in:
Zheng Xi Zhou
2022-01-19 20:47:39 +08:00
parent 4e881b44af
commit bc06a5343e
4 changed files with 108 additions and 10 deletions
+2
View File
@@ -44,6 +44,8 @@ const (
FlagProvider = "provider"
// FlagGit command flag to specify which git repository the configuration(HCL) is stored in
FlagGit = "git"
// FlagLocal command flag to specify the local path of Terraform module or resource HCL file
FlagLocal = "local"
// FlagPath command flag to specify which path the configuration(HCL) is stored in the Git repository
FlagPath = "path"
// FlagNamespace command flag to specify which namespace to use
+34 -10
View File
@@ -21,6 +21,7 @@ import (
"bytes"
"context"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path"
@@ -167,8 +168,10 @@ func NewDefinitionInitCommand(c common.Args) *cobra.Command {
"> vela def init my-def -i --output ./my-def.cue\n" +
"# Command below initiate a ComponentDefinition named my-webservice with the template parsed from ./template.yaml.\n" +
"> vela def init my-webservice -i --template-yaml ./template.yaml\n" +
"# Command below initiate a typed ComponentDefinition named vswitch from Alibaba Cloud.\n" +
"> vela def init vswitch --type component --provider alibaba --desc xxx --git https://github.com/kubevela-contrib/terraform-modules.git --path alibaba/vswitch",
"# Initiate a Terraform ComponentDefinition named vswitch from Github for Alibaba Cloud.\n" +
"> vela def init vswitch --type component --provider alibaba --desc xxx --git https://github.com/kubevela-contrib/terraform-modules.git --path alibaba/vswitch\n" +
"# Initiate a Terraform ComponentDefinition named redis from local file for AWS.\n" +
"> vela def init redis --type component --provider aws --desc \"Terraform configuration for AWS Redis\" --local redis.tf",
Args: cobra.ExactValidArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
var defStr string
@@ -280,6 +283,7 @@ func NewDefinitionInitCommand(c common.Args) *cobra.Command {
cmd.Flags().BoolP(FlagInteractive, "i", false, "Specify whether use interactive process to help generate definitions.")
cmd.Flags().StringP(FlagProvider, "p", "", "Specify which provider the cloud resource definition belongs to. Only `alibaba`, `aws`, `azure` are supported.")
cmd.Flags().StringP(FlagGit, "", "", "Specify which git repository the configuration(HCL) is stored in. Valid when --provider/-p is set.")
cmd.Flags().StringP(FlagLocal, "", "", "Specify the local path of the configuration(HCL) file. Valid when --provider/-p is set.")
cmd.Flags().StringP(FlagPath, "", "", "Specify which path the configuration(HCL) is stored in the Git repository. Valid when --git is set.")
return cmd
}
@@ -290,18 +294,42 @@ func generateTerraformTypedComponentDefinition(cmd *cobra.Command, name, kind, p
}
switch provider {
case "aws", "azure", "alibaba":
case "aws", "azure", "alibaba", "tencent":
var terraform *commontype.Terraform
git, err := cmd.Flags().GetString(FlagGit)
if err != nil {
return "", errors.Wrapf(err, "failed to get `%s`", FlagGit)
}
if !strings.HasPrefix(git, "https://") || !strings.HasSuffix(git, ".git") {
return "", errors.Errorf("invalid git url: %s", git)
local, err := cmd.Flags().GetString(FlagLocal)
if err != nil {
return "", errors.Wrapf(err, "failed to get `%s`", FlagLocal)
}
if git != "" && local != "" {
return "", errors.New("only one of --git and --local can be set")
}
gitPath, err := cmd.Flags().GetString(FlagPath)
if err != nil {
return "", errors.Wrapf(err, "failed to get `%s`", FlagPath)
}
if git != "" {
if !strings.HasPrefix(git, "https://") || !strings.HasSuffix(git, ".git") {
return "", errors.Errorf("invalid git url: %s", git)
}
terraform = &commontype.Terraform{
Configuration: git,
Type: "remote",
Path: gitPath,
}
} else if local != "" {
hcl, err := ioutil.ReadFile(filepath.Clean(local))
if err != nil {
return "", errors.Wrapf(err, "failed to read Terraform configuration from file %s", local)
}
terraform = &commontype.Terraform{
Configuration: string(hcl),
}
}
def := v1beta1.ComponentDefinition{
TypeMeta: metav1.TypeMeta{
APIVersion: "core.oam.dev/v1beta1",
@@ -325,11 +353,7 @@ func generateTerraformTypedComponentDefinition(cmd *cobra.Command, name, kind, p
},
},
Schematic: &commontype.Schematic{
Terraform: &commontype.Terraform{
Configuration: git,
Type: "remote",
Path: gitPath,
},
Terraform: terraform,
},
},
}
+14
View File
@@ -215,6 +215,10 @@ func TestNewDefinitionInitCommand4Terraform(t *testing.T) {
name: "normal",
args: []string{"vswitch", "-t", "component", "--provider", "alibaba", "--desc", "xxx", "--git", "https://github.com/kubevela-contrib/terraform-modules.git", "--path", "alibaba/vswitch"},
},
{
name: "normal from local",
args: []string{"vswitch", "-t", "component", "--provider", "tencent", "--desc", "xxx", "--local", "test-data/redis.tf"},
},
{
name: "print in a file",
args: []string{"vswitch", "-t", "component", "--provider", "alibaba", "--desc", "xxx", "--git", "https://github.com/kubevela-contrib/terraform-modules.git", "--path", "alibaba/vswitch", "--output", defFileName},
@@ -255,6 +259,16 @@ status: {}`,
args: []string{"vswitch", "-t", "component", "--provider", "alibaba", "--desc", "test", "--git", "xxx"},
errMsg: "invalid git url",
},
{
name: "git and local could be set at the same time",
args: []string{"vswitch", "-t", "component", "--provider", "alibaba", "--desc", "test", "--git", "xxx", "--local", "yyy"},
errMsg: "only one of --git and --local can be set",
},
{
name: "local file doesn't exist",
args: []string{"vswitch", "-t", "component", "--provider", "tencent", "--desc", "xxx", "--local", "test-data/redis2.tf"},
errMsg: "failed to read Terraform configuration from file",
},
}
for _, tc := range testcases {
+58
View File
@@ -0,0 +1,58 @@
terraform {
required_providers {
tencentcloud = {
source = "tencentcloudstack/tencentcloud"
}
}
}
resource "tencentcloud_redis_instance" "main" {
type_id = 8
availability_zone = var.availability_zone
name = var.instance_name
password = var.user_password
mem_size = var.mem_size
port = var.port
}
output "DB_IP" {
value = tencentcloud_redis_instance.main.ip
}
output "DB_PASSWORD" {
value = var.user_password
}
output "DB_PORT" {
value = var.port
}
variable "availability_zone" {
description = "The available zone ID of an instance to be created."
type = string
default = "ap-chengdu-1"
}
variable "instance_name" {
description = "redis instance name"
type = string
default = "sample"
}
variable "user_password" {
description = "redis instance password"
type = string
default = "IEfewjf2342rfwfwYYfaked"
}
variable "mem_size" {
description = "redis instance memory size"
type = number
default = 1024
}
variable "port" {
description = "The port used to access a redis instance."
type = number
default = 6379
}