Skip to content

Commit

Permalink
Refactor constructing containers and support checkout certain git refs (
Browse files Browse the repository at this point in the history
  • Loading branch information
chivalryq committed Sep 25, 2023
1 parent 3536da5 commit 966471a
Show file tree
Hide file tree
Showing 24 changed files with 542 additions and 307 deletions.
44 changes: 27 additions & 17 deletions controllers/process/const.go → api/types/const.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
package process
package types

const (
// WorkingVolumeMountPath is the mount path for working volume
WorkingVolumeMountPath = "/data"
// InputTFConfigurationVolumeName is the volume name for input Terraform Configuration
InputTFConfigurationVolumeName = "tf-input-configuration"
// BackendVolumeName is the volume name for Terraform backend
BackendVolumeName = "tf-backend"
// InputTFConfigurationVolumeMountPath is the volume mount path for input Terraform Configuration
InputTFConfigurationVolumeMountPath = "/opt/tf-configuration"
// BackendVolumeMountPath is the volume mount path for Terraform backend
BackendVolumeMountPath = "/opt/tf-backend"
DefaultNamespace = "default"

GitCredsKnownHosts = "known_hosts"
// Terraform credentials
// TerraformCredentials -
TerraformCredentials = "credentials.tfrc.json"
// Terraform Registry Configuration
// TerraformRegistryConfig -
TerraformRegistryConfig = ".terraformrc"
)

const (
// TerraformContainerName is the name of the container that executes terraform in the pod
TerraformContainerName = "terraform-executor"
TerraformInitContainerName = "terraform-init"
)

const (
// TFInputConfigMapName is the CM name for Terraform Input Configuration
TFInputConfigMapName = "tf-%s"
Expand All @@ -43,23 +40,36 @@ const (
ServiceAccountName = "tf-executor-service-account"
)

// Volume names and mount paths
const (
defaultNamespace = "default"
// TerraformContainerName is the name of the container that executes terraform in the pod
TerraformContainerName = "terraform-executor"
TerraformInitContainerName = "terraform-init"
// WorkingVolumeMountPath is the mount path for working volume
WorkingVolumeMountPath = "/data"

// InputTFConfigurationVolumeName is the volume name for input Terraform Configuration
InputTFConfigurationVolumeName = "tf-input-configuration"
// InputTFConfigurationVolumeMountPath is the volume mount path for input Terraform Configuration
InputTFConfigurationVolumeMountPath = "/opt/tf-configuration"

// BackendVolumeName is the volume name for Terraform backend
BackendVolumeName = "tf-backend"
// BackendVolumeMountPath is the volume mount path for Terraform backend
BackendVolumeMountPath = "/opt/tf-backend"

// GitAuthConfigVolumeName is the volume name for git auth configurtaion
GitAuthConfigVolumeName = "git-auth-configuration"
// GitAuthConfigVolumeMountPath is the volume mount path for git auth configurtaion
GitAuthConfigVolumeMountPath = "/root/.ssh"

// TerraformCredentialsConfigVolumeName is the volume name for terraform auth configurtaion
TerraformCredentialsConfigVolumeName = "terraform-credentials-configuration"
// TerraformCredentialsConfigVolumeMountPath is the volume mount path for terraform auth configurtaion
TerraformCredentialsConfigVolumeMountPath = "/root/.terraform.d"

// TerraformRCConfigVolumeName is the volume name of the terraform registry configuration
TerraformRCConfigVolumeName = "terraform-rc-configuration"
// TerraformRCConfigVolumeMountPath is the volume mount path for registry configuration
TerraformRCConfigVolumeMountPath = "/root"

// TerraformCredentialsHelperConfigVolumeName is the volume name for terraform auth configurtaion
TerraformCredentialsHelperConfigVolumeName = "terraform-credentials-helper-configuration"
// TerraformCredentialsHelperConfigVolumeMountPath is the volume mount path for terraform auth configurtaion
Expand Down
4 changes: 2 additions & 2 deletions api/types/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ const (
type Stage string

const (
TerraformInit Stage = "TerraformInit"
TerraformApply Stage = "TerraformApply"
InitStage Stage = "InitStage"
ApplyStage Stage = "Apply"
)

const (
Expand Down
19 changes: 19 additions & 0 deletions api/types/terraform.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package types

import "k8s.io/apimachinery/pkg/api/resource"

const (
// TerraformHCLConfigurationName is the file name for Terraform hcl Configuration
TerraformHCLConfigurationName = "main.tf"
Expand All @@ -15,9 +17,26 @@ const (
ConfigurationRemote ConfigurationType = "Remote"
)

type Git struct {
URL string
Path string
Ref GitRef
}

// GitRef specifies the git reference
type GitRef struct {
Branch string `json:"branch,omitempty"`
Tag string `json:"tag,omitempty"`
Commit string `json:"commit,omitempty"`
}

type ResourceQuota struct {
ResourcesLimitsCPU string
ResourcesLimitsCPUQuantity resource.Quantity
ResourcesLimitsMemory string
ResourcesLimitsMemoryQuantity resource.Quantity
ResourcesRequestsCPU string
ResourcesRequestsCPUQuantity resource.Quantity
ResourcesRequestsMemory string
ResourcesRequestsMemoryQuantity resource.Quantity
}
2 changes: 1 addition & 1 deletion api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions api/v1beta2/configuration_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ type ConfigurationSpec struct {
// Remote is a git repo which contains hcl files. Currently, only public git repos are supported.
Remote string `json:"remote,omitempty"`

// GitRef is the git branch or tag or commit hash to checkout. Only used when Remote is specified.
GitRef apitypes.GitRef `json:"gitRef,omitempty"`

// +kubebuilder:pruning:PreserveUnknownFields
Variable *runtime.RawExtension `json:"variable,omitempty"`

Expand Down
2 changes: 1 addition & 1 deletion api/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions chart/crds/terraform.core.oam.dev_configurations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,17 @@ spec:
name must be unique.
type: string
type: object
gitRef:
description: GitRef is the git branch or tag or commit hash to checkout.
Only used when Remote is specified.
properties:
branch:
type: string
commit:
type: string
tag:
type: string
type: object
hcl:
description: HCL is the Terraform HCL type configuration
type: string
Expand Down
10 changes: 5 additions & 5 deletions controllers/configuration_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (r *ConfigurationReconciler) Reconcile(ctx context.Context, req ctrl.Reques
klog.InfoS("performing Configuration Destroy", "Namespace", req.Namespace, "Name", req.Name, "JobName", meta.DestroyJobName)
// if allow to delete halfway, we will not check the status of the apply job.

_, err := terraform.GetTerraformStatus(ctx, meta.ControllerNamespace, meta.DestroyJobName, process.TerraformContainerName, process.TerraformInitContainerName)
_, err := terraform.GetTerraformStatus(ctx, meta.ControllerNamespace, meta.DestroyJobName, types.TerraformContainerName, types.TerraformInitContainerName)
if err != nil {
klog.ErrorS(err, "Terraform destroy failed")
if updateErr := meta.UpdateDestroyStatus(ctx, r.Client, types.ConfigurationDestroyFailed, err.Error()); updateErr != nil {
Expand Down Expand Up @@ -151,7 +151,7 @@ func (r *ConfigurationReconciler) Reconcile(ctx context.Context, req ctrl.Reques
}
return ctrl.Result{RequeueAfter: 3 * time.Second}, errors.Wrap(err, "failed to create/update cloud resource")
}
state, err := terraform.GetTerraformStatus(ctx, meta.ControllerNamespace, meta.ApplyJobName, process.TerraformContainerName, process.TerraformInitContainerName)
state, err := terraform.GetTerraformStatus(ctx, meta.ControllerNamespace, meta.ApplyJobName, types.TerraformContainerName, types.TerraformInitContainerName)
if err != nil {
klog.ErrorS(err, "Terraform apply failed")
if updateErr := meta.UpdateApplyStatus(ctx, r.Client, state, err.Error()); updateErr != nil {
Expand All @@ -173,7 +173,7 @@ func (r *ConfigurationReconciler) terraformApply(ctx context.Context, configurat

if err := meta.GetApplyJob(ctx, k8sClient, &tfExecutionJob); err != nil {
if kerrors.IsNotFound(err) {
return meta.AssembleAndTriggerJob(ctx, k8sClient, process.TerraformApply)
return meta.AssembleAndTriggerJob(ctx, k8sClient, types.TerraformApply)
}
}
klog.InfoS("terraform apply job", "Namespace", tfExecutionJob.Namespace, "Name", tfExecutionJob.Name)
Expand Down Expand Up @@ -229,7 +229,7 @@ func (r *ConfigurationReconciler) terraformDestroy(ctx context.Context, configur
if err := k8sClient.Get(ctx, client.ObjectKey{Name: meta.DestroyJobName, Namespace: meta.ControllerNamespace}, &destroyJob); err != nil {
if kerrors.IsNotFound(err) {
if err := r.Client.Get(ctx, client.ObjectKey{Name: configuration.Name, Namespace: configuration.Namespace}, &v1beta2.Configuration{}); err == nil {
if err = meta.AssembleAndTriggerJob(ctx, k8sClient, process.TerraformDestroy); err != nil {
if err = meta.AssembleAndTriggerJob(ctx, k8sClient, types.TerraformDestroy); err != nil {
return err
}
}
Expand Down Expand Up @@ -480,7 +480,7 @@ func (r *ConfigurationReconciler) preCheck(ctx context.Context, configuration *v
return err
}

return util.CreateTerraformExecutorClusterRole(ctx, k8sClient, fmt.Sprintf("%s-%s", meta.ControllerNamespace, process.ClusterRoleName))
return util.CreateTerraformExecutorClusterRole(ctx, k8sClient, fmt.Sprintf("%s-%s", meta.ControllerNamespace, types.ClusterRoleName))
}

// SetupWithManager setups with a manager
Expand Down
14 changes: 7 additions & 7 deletions controllers/configuration_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func TestConfigurationReconcile(t *testing.T) {

applyingJob2 := &batchv1.Job{
ObjectMeta: metav1.ObjectMeta{
Name: req.Name + "-" + string(process.TerraformApply),
Name: req.Name + "-" + string(types.TerraformApply),
Namespace: req.Namespace,
},
Status: batchv1.JobStatus{
Expand All @@ -153,7 +153,7 @@ func TestConfigurationReconcile(t *testing.T) {

variableSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf(process.TFVariableSecret, req.Name),
Name: fmt.Sprintf(types.TFVariableSecret, req.Name),
Namespace: req.Namespace,
},
Data: map[string][]byte{
Expand Down Expand Up @@ -306,7 +306,7 @@ terraform {
varMap := map[string]string{"name": "abc"}
appliedEnvVariable := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf(process.TFVariableSecret, req.Name),
Name: fmt.Sprintf(types.TFVariableSecret, req.Name),
Namespace: req.Namespace,
},
Data: map[string][]byte{
Expand All @@ -318,7 +318,7 @@ terraform {
},
Type: corev1.SecretTypeOpaque,
}
appliedJobName := req.Name + "-" + string(process.TerraformApply)
appliedJobName := req.Name + "-" + string(types.TerraformApply)
appliedJob := &batchv1.Job{
ObjectMeta: metav1.ObjectMeta{
Name: appliedJobName,
Expand Down Expand Up @@ -1165,7 +1165,7 @@ func TestTerraformDestroy(t *testing.T) {
}
baseVariableSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf(process.TFVariableSecret, secretSuffix),
Name: fmt.Sprintf(types.TFVariableSecret, secretSuffix),
Namespace: controllerNamespace,
},
Type: corev1.SecretTypeOpaque,
Expand Down Expand Up @@ -1197,7 +1197,7 @@ func TestTerraformDestroy(t *testing.T) {
Name: baseProvider.Name,
Namespace: baseProvider.Namespace,
},
VariableSecretName: fmt.Sprintf(process.TFVariableSecret, secretSuffix),
VariableSecretName: fmt.Sprintf(types.TFVariableSecret, secretSuffix),
ConfigurationCMName: configurationCMName,
// True is default value if user ignores configuration.Spec.DeleteResource
DeleteResource: true,
Expand All @@ -1208,7 +1208,7 @@ func TestTerraformDestroy(t *testing.T) {
ApplyJobName: applyJobName,
DestroyJobName: destroyJobName,
ConfigurationCMName: configurationCMName,
VariableSecretName: fmt.Sprintf(process.TFVariableSecret, secretSuffix),
VariableSecretName: fmt.Sprintf(types.TFVariableSecret, secretSuffix),
}

metaWithDeleteResourceIsFalse := baseMeta
Expand Down
60 changes: 60 additions & 0 deletions controllers/process/container/apply.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package container

import (
"fmt"

"github.com/oam-dev/terraform-controller/api/types"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
)

func (a *Assembler) ApplyContainer(executionType types.TerraformExecutionType, resourceQuota types.ResourceQuota) v1.Container {

c := v1.Container{
Name: types.TerraformContainerName,
Image: a.TerraformImage,
ImagePullPolicy: v1.PullIfNotPresent,
Command: []string{
"bash",
"-c",
fmt.Sprintf("terraform %s -lock=false -auto-approve", executionType),
},
VolumeMounts: []v1.VolumeMount{
{
Name: a.Name,
MountPath: types.WorkingVolumeMountPath,
},
{
Name: types.InputTFConfigurationVolumeName,
MountPath: types.InputTFConfigurationVolumeMountPath,
},
},
Env: a.Envs,
}

if resourceQuota.ResourcesLimitsCPU != "" || resourceQuota.ResourcesLimitsMemory != "" ||
resourceQuota.ResourcesRequestsCPU != "" || resourceQuota.ResourcesRequestsMemory != "" {
resourceRequirements := v1.ResourceRequirements{}
if resourceQuota.ResourcesLimitsCPU != "" || resourceQuota.ResourcesLimitsMemory != "" {
resourceRequirements.Limits = map[v1.ResourceName]resource.Quantity{}
if resourceQuota.ResourcesLimitsCPU != "" {
resourceRequirements.Limits["cpu"] = resourceQuota.ResourcesLimitsCPUQuantity
}
if resourceQuota.ResourcesLimitsMemory != "" {
resourceRequirements.Limits["memory"] = resourceQuota.ResourcesLimitsMemoryQuantity
}
}
if resourceQuota.ResourcesRequestsCPU != "" || resourceQuota.ResourcesLimitsMemory != "" {
resourceRequirements.Requests = map[v1.ResourceName]resource.Quantity{}
if resourceQuota.ResourcesRequestsCPU != "" {
resourceRequirements.Requests["cpu"] = resourceQuota.ResourcesRequestsCPUQuantity
}
if resourceQuota.ResourcesRequestsMemory != "" {
resourceRequirements.Requests["memory"] = resourceQuota.ResourcesRequestsMemoryQuantity
}
}
c.Resources = resourceRequirements
}

return c
}
Loading

0 comments on commit 966471a

Please sign in to comment.