Skip to content

Commit

Permalink
Merge pull request #130 from zzxwill/log
Browse files Browse the repository at this point in the history
Fetch terraform log
  • Loading branch information
zzxwill authored Oct 17, 2021
2 parents 6241741 + 051b4ea commit 4d83fbc
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 278 deletions.
3 changes: 3 additions & 0 deletions api/types/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ const (
Available ConfigurationState = "Available"
ConfigurationProvisioningAndChecking ConfigurationState = "ProvisioningAndChecking"
ConfigurationDestroying ConfigurationState = "Destroying"
ConfigurationApplyFailed ConfigurationState = "ApplyFailed"
ConfigurationDestroyFailed ConfigurationState = "DestroyFailed"
ConfigurationReloading ConfigurationState = "ConfigurationReloading"
)

// ProviderState is the type for Provider state
Expand Down
12 changes: 12 additions & 0 deletions chart/templates/tf_controller_clusterrole.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,15 @@ rules:
verbs:
- "list"
- "watch"

- apiGroups:
- ""
resources:
- pods/log
- pods
verbs:
- get
- list
- create
- update
- delete
71 changes: 2 additions & 69 deletions controllers/configuration/configuration.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
package configuration

import (
"fmt"
"os"
"os/exec"
"path"
"strings"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/pkg/errors"
Expand Down Expand Up @@ -39,7 +33,7 @@ func ValidConfigurationObject(configuration *v1beta1.Configuration) (types.Confi
}

// RenderConfiguration will compose the Terraform configuration with hcl/json and backend
func RenderConfiguration(configuration *v1beta1.Configuration, controllerNamespace string, configurationType types.ConfigurationType, preState bool) (string, error) {
func RenderConfiguration(configuration *v1beta1.Configuration, controllerNamespace string, configurationType types.ConfigurationType) (string, error) {
if configuration.Spec.Backend != nil {
if configuration.Spec.Backend.SecretSuffix == "" {
configuration.Spec.Backend.SecretSuffix = configuration.Name
Expand All @@ -61,9 +55,7 @@ func RenderConfiguration(configuration *v1beta1.Configuration, controllerNamespa
return configuration.Spec.JSON, nil
case types.ConfigurationHCL:
completedConfiguration := configuration.Spec.HCL
if !preState {
completedConfiguration += "\n" + backendTF
}
completedConfiguration += "\n" + backendTF
return completedConfiguration, nil
case types.ConfigurationRemote:
return backendTF, nil
Expand Down Expand Up @@ -105,62 +97,3 @@ func CompareTwoContainerEnvs(s1 []v1.EnvVar, s2 []v1.EnvVar) bool {
}
return cmp.Diff(s1, s2, cmpopts.SortSlices(less)) == ""
}

// checkTerraformSyntax checks the syntax error and state for a HCL/JSON configuration
func checkTerraformSyntax(name, configuration string) (bool, error) {
klog.InfoS("About to check syntax issues", "Configuration", name)
state := false
dir, osErr := os.MkdirTemp("", fmt.Sprintf("tf-validate-%s-", name))
if osErr != nil {
klog.ErrorS(osErr, "Failed to create folder", "Dir", dir)
return state, osErr
}
defer os.RemoveAll(dir) //nolint:errcheck
tfFile := fmt.Sprintf("%s/main.tf", dir)
if err := os.WriteFile(tfFile, []byte(configuration), 0777); err != nil { //nolint
klog.ErrorS(err, "Failed to write Configuration hcl to main.tf", "HCL", configuration)
return state, err
}
if err := os.Chdir(dir); err != nil {
klog.ErrorS(err, "Failed to change dir", "dir", dir)
return state, err
}

var (
output []byte
err error
)
output, err = exec.Command("terraform", "init").CombinedOutput()
if err != nil {
klog.ErrorS(err, "The command execution isn't successful", "cmd", "terraform init", "output", string(output))
} else {
output, err = exec.Command("terraform", "validate").CombinedOutput()
if err != nil {
klog.ErrorS(err, "The command execution isn't successful", "cmd", "terraform validate", "output", string(output))
}
_, err := os.Stat(path.Join(dir, "/.terraform/terraform.tfstate"))
if err == nil {
state = true
}
}
if strings.Contains(string(output), "Success!") {
return state, nil
}
return state, errors.New(string(output))
}

// CheckConfigurationSyntax checks the syntax of Configuration
func CheckConfigurationSyntax(configuration *v1beta1.Configuration, configurationType types.ConfigurationType) (bool, error) {
var template string
switch configurationType {
case types.ConfigurationHCL:
template = configuration.Spec.HCL
case types.ConfigurationJSON:
template = configuration.Spec.JSON
case types.ConfigurationRemote:
// TODO(zzxwill) check syntax issue
return false, nil

}
return checkTerraformSyntax(configuration.Name, template)
}
184 changes: 0 additions & 184 deletions controllers/configuration/configuration_test.go
Original file line number Diff line number Diff line change
@@ -1,185 +1 @@
package configuration

import (
"os"
"strings"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
)

func TestCompareTwoContainerEnvs(t *testing.T) {
cases := map[string]struct {
s1 []v1.EnvVar
s2 []v1.EnvVar
want bool
}{
"Equal": {
s1: []v1.EnvVar{
{
Name: "TF_VAR_zone_id",
Value: "cn-beijing-z",
},
{
Name: "E1",
Value: "V1",
},
{
Name: "NAME",
Value: "aaa",
},
},
s2: []v1.EnvVar{

{
Name: "NAME",
Value: "aaa",
},
{
Name: "TF_VAR_zone_id",
Value: "cn-beijing-z",
},
{
Name: "E1",
Value: "V1",
},
},
want: true,
},
"Not Equal": {
s1: []v1.EnvVar{
{
Name: "NAME",
Value: "aaa",
},
},
s2: []v1.EnvVar{

{
Name: "NAME",
Value: "bbb",
},
},
want: false,
},
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
equal := CompareTwoContainerEnvs(tc.s1, tc.s2)
if equal != tc.want {
if diff := cmp.Diff(tc.want, equal); diff != "" {
t.Errorf("\nCompareTwoContainerEnvs(...) %s\n", diff)
}
}
})
}
}

func TestCheckTFConfiguration(t *testing.T) {
cases := map[string]struct {
name string
configuration string
subStr string
state bool
}{
"Invalid": {
name: "bad",
configuration: `resource2 "alicloud_oss_bucket" "bucket-acl" {
bucket = var.bucket
acl = var.acl
}
output "BUCKET_NAME" {
value = "${alicloud_oss_bucket.bucket-acl.bucket}.${alicloud_oss_bucket.bucket-acl.extranet_endpoint}"
}
variable "bucket" {
description = "OSS bucket name"
default = "vela-website"
type = string
}
variable "acl" {
description = "OSS bucket ACL, supported 'private', 'public-read', 'public-read-write'"
default = "private"
type = string
}
`,
subStr: "Error:",
state: false,
},
"valid": {
name: "good",
configuration: `resource "alicloud_oss_bucket" "bucket-acl" {
bucket = var.bucket
acl = var.acl
}
output "BUCKET_NAME" {
value = "${alicloud_oss_bucket.bucket-acl.bucket}.${alicloud_oss_bucket.bucket-acl.extranet_endpoint}"
}
variable "bucket" {
description = "OSS bucket name"
default = "vela-website"
type = string
}
variable "acl" {
description = "OSS bucket ACL, supported 'private', 'public-read', 'public-read-write'"
default = "private"
type = string
}`,
subStr: "",
state: false,
},
"valid-with-state": {
name: "good",
configuration: `resource "alicloud_oss_bucket" "bucket-acl" {
bucket = var.bucket
acl = var.acl
}
output "BUCKET_NAME" {
value = "${alicloud_oss_bucket.bucket-acl.bucket}.${alicloud_oss_bucket.bucket-acl.extranet_endpoint}"
}
variable "bucket" {
description = "OSS bucket name"
default = "vela-website"
type = string
}
variable "acl" {
description = "OSS bucket ACL, supported 'private', 'public-read', 'public-read-write'"
default = "private"
type = string
}
terraform {
backend "local" {
path = "./test.tfstate"
}
}`,
subStr: "",
state: true,
},
}
// As the entry point is the root folder `terraform-controller`, the unit-test locates here `./controllers/configuration`,
// so we change the directory
os.Chdir("../../")
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
r := require.New(t)
state, err := checkTerraformSyntax(tc.name, tc.configuration)
if err != nil {
if !strings.Contains(err.Error(), tc.subStr) {
t.Errorf("\ncheckTFConfiguration(...) %s\n", cmp.Diff(err.Error(), tc.subStr))
}
}
r.Equal(state, tc.state)
})
}
}
Loading

0 comments on commit 4d83fbc

Please sign in to comment.