Skip to content

Commit

Permalink
[FEATURE] - Switching to Opentofu
Browse files Browse the repository at this point in the history
Currently we are using the hashicorp image and binary, this PR changes the default implementation to opentofu
  • Loading branch information
gambol99 committed Nov 9, 2024
1 parent 4e13e0a commit 24730ae
Show file tree
Hide file tree
Showing 9 changed files with 37 additions and 22 deletions.
3 changes: 2 additions & 1 deletion cmd/controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func main() {
flags.StringSliceVar(&config.ExecutorSecrets, "executor-secret", []string{}, "Name of a secret in controller namespace which should be added to the job")
flags.StringSliceVar(&config.JobLabels, "job-label", []string{}, "A collection of key=values to add to all jobs")
flags.StringVar(&config.BackendTemplate, "backend-template", "", "Name of secret in the controller namespace containing a template for the terraform state")
flags.StringVar(&config.BinaryPath, "binary-path", "/bin/opentufo", "The path of the terraform binary to use")
flags.StringVar(&config.ExecutorCPULimit, "executor-cpu-limit", "", "The default CPU limit for the executor container (default is no limit)")
flags.StringVar(&config.ExecutorCPURequest, "executor-cpu-request", "5m", "The default CPU request for the executor container")
flags.StringVar(&config.ExecutorImage, "executor-image", fmt.Sprintf("ghcr.io/appvia/terranetes-executor:%s", version.Version), "The image to use for the executor")
Expand All @@ -93,7 +94,7 @@ func main() {
flags.StringVar(&config.TLSCert, "tls-cert", "tls.pem", "The name of the file containing the TLS certificate")
flags.StringVar(&config.TLSDir, "tls-dir", "", "The directory the certificates are held")
flags.StringVar(&config.TLSKey, "tls-key", "tls-key.pem", "The name of the file containing the TLS key")
flags.StringVar(&config.TerraformImage, "terraform-image", "hashicorp/terraform:latest", "The image to use for the terraform")
flags.StringVar(&config.TerraformImage, "terraform-image", "ghcr.io/opentofu/opentofu:latest", "The image to use for the terraform")

crFlags := flag.NewFlagSet("controller-runtime", flag.ContinueOnError)
zapOpts.BindFlags(crFlags)
Expand Down
17 changes: 9 additions & 8 deletions pkg/assets/job.yaml.tpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
---
{{ $binary := .BinaryPath }}
apiVersion: batch/v1
kind: Job
metadata:
Expand Down Expand Up @@ -122,10 +123,10 @@ spec:
mountPath: /data

- name: init
image: {{ .Images.Terraform }}
image: {{ .Images.Image }}
workingDir: /data
command:
- /bin/terraform
- {{ $binary }}
args:
- init
env:
Expand Down Expand Up @@ -195,17 +196,17 @@ spec:

containers:
- name: {{ .TerraformContainerName }}
image: {{ .Images.Terraform }}
image: {{ .Images.Image }}
imagePullPolicy: {{ .ImagePullPolicy }}
workingDir: /data
command:
- /run/bin/step
args:
- --comment=Executing Terraform
{{- if eq .Stage "plan" }}
- --command=/bin/terraform plan {{ .TerraformArguments }} -out=/run/plan.out -lock=false -no-color -input=false
- --command={{ $binary }} plan {{ .TerraformArguments }} -out=/run/plan.out -lock=false -no-color -input=false
# We need to retain a uncompressed version, for checkov and infracosts
- --command=/bin/terraform show -json /run/plan.out > /run/tfplan.json
- --command={{ $binary }} show -json /run/plan.out > /run/tfplan.json
- --command=/bin/cp /run/tfplan.json /run/plan.json
- --command=/bin/gzip /run/plan.json
- --command=/bin/mv /run/plan.json.gz /run/plan.json
Expand All @@ -214,17 +215,17 @@ spec:
- --upload=$(TERRAFORM_PLAN_OUT_NAME)=/run/plan.out
{{- end }}
{{- if eq .Stage "apply" }}
- --command=/bin/terraform apply {{ .TerraformArguments }} -lock=false -no-color -input=false -auto-approve
- --command={{ $binary }} apply {{ .TerraformArguments }} -lock=false -no-color -input=false -auto-approve
{{- if .SaveTerraformState }}
- --command=/bin/terraform state pull > /run/tfstate
- --command={{ $binary }} state pull > /run/tfstate
- --command=/bin/gzip /run/tfstate
- --command=/bin/mv /run/tfstate.gz /run/tfstate
- --namespace=$(KUBE_NAMESPACE)
- --upload=$(TERRAFORM_STATE_NAME)=/run/tfstate
{{- end }}
{{- end }}
{{- if eq .Stage "destroy" }}
- --command=/bin/terraform destroy {{ .TerraformArguments }} -auto-approve
- --command={{ $binary }} destroy {{ .TerraformArguments }} -auto-approve
{{- end }}
- --on-error=/run/steps/terraform.failed
- --on-success=/run/steps/terraform.complete
Expand Down
2 changes: 2 additions & 0 deletions pkg/controller/configuration/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ type Controller struct {
// BackoffLimit is the amount of times we are allowing a job to failed before deeming
// it a failure
BackoffLimit int
// BinaryPath is the name of the binary to use to run the terraform commands
BinaryPath string
// EnableContextInjection enables the injection of the context into the terraform configuration
// variables. This means we shall inject an number of default variables into the configuration
// such as namespace, name and labels
Expand Down
3 changes: 2 additions & 1 deletion pkg/controller/configuration/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,15 @@ func (c *Controller) ensureTerraformDestroy(configuration *terraformv1alpha1.Con
terraformv1alpha1.RetryAnnotation: configuration.GetAnnotations()[terraformv1alpha1.RetryAnnotation],
}),
BackoffLimit: c.BackoffLimit,
BinaryPath: c.BinaryPath,
EnableInfraCosts: c.EnableInfracosts,
ExecutorImage: c.ExecutorImage,
ExecutorSecrets: c.ExecutorSecrets,
InfracostsImage: c.InfracostsImage,
InfracostsSecret: c.InfracostsSecretName,
Namespace: c.ControllerNamespace,
Template: state.jobTemplate,
TerraformImage: GetTerraformImage(configuration, c.TerraformImage),
Image: GetTerraformImage(configuration, c.TerraformImage),
})
if err != nil {
cond.Failed(err, "Failed to create the terraform destroy job")
Expand Down
6 changes: 4 additions & 2 deletions pkg/controller/configuration/ensure.go
Original file line number Diff line number Diff line change
Expand Up @@ -816,21 +816,22 @@ func (c *Controller) ensureTerraformPlan(configuration *terraformv1alpha1.Config
terraformv1alpha1.JobTemplateHashLabel: state.jobTemplateHash,
}),
BackoffLimit: c.BackoffLimit,
BinaryPath: c.BinaryPath,
DefaultExecutorCPULimit: c.DefaultExecutorCPULimit,
DefaultExecutorCPURequest: c.DefaultExecutorCPURequest,
DefaultExecutorMemoryLimit: c.DefaultExecutorMemoryLimit,
DefaultExecutorMemoryRequest: c.DefaultExecutorMemoryRequest,
EnableInfraCosts: c.EnableInfracosts,
ExecutorImage: c.ExecutorImage,
ExecutorSecrets: c.ExecutorSecrets,
Image: GetTerraformImage(configuration, c.TerraformImage),
InfracostsImage: c.InfracostsImage,
InfracostsSecret: c.InfracostsSecretName,
Namespace: c.ControllerNamespace,
PolicyConstraint: state.checkovConstraint,
PolicyImage: c.PolicyImage,
SaveTerraformState: saveState,
Template: state.jobTemplate,
TerraformImage: GetTerraformImage(configuration, c.TerraformImage),
}

// @step: use the options to generate the job
Expand Down Expand Up @@ -1255,6 +1256,7 @@ func (c *Controller) ensureTerraformApply(configuration *terraformv1alpha1.Confi
},
),
BackoffLimit: c.BackoffLimit,
BinaryPath: c.BinaryPath,
EnableInfraCosts: c.EnableInfracosts,
ExecutorImage: c.ExecutorImage,
ExecutorSecrets: c.ExecutorSecrets,
Expand All @@ -1263,7 +1265,7 @@ func (c *Controller) ensureTerraformApply(configuration *terraformv1alpha1.Confi
Namespace: c.ControllerNamespace,
SaveTerraformState: saveState,
Template: state.jobTemplate,
TerraformImage: GetTerraformImage(configuration, c.TerraformImage),
Image: GetTerraformImage(configuration, c.TerraformImage),
})
if err != nil {
cond.Failed(err, "Failed to create the terraform apply job")
Expand Down
16 changes: 9 additions & 7 deletions pkg/controller/configuration/reconcile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func makeFakeController(cc client.Client) *Controller {
cache: cache.New(5*time.Minute, 10*time.Minute),
recorder: recorder,
BackoffLimit: 2,
BinaryPath: "/bin/opentofu",
ControllerNamespace: "terraform-system",
DefaultExecutorCPULimit: "1",
DefaultExecutorCPURequest: "5m",
Expand All @@ -71,7 +72,7 @@ func makeFakeController(cc client.Client) *Controller {
ExecutorImage: "ghcr.io/appvia/terranetes-executor",
InfracostsImage: "infracosts/infracost:latest",
PolicyImage: "bridgecrew/checkov:2.0.1140",
TerraformImage: "hashicorp/terraform:1.1.9",
TerraformImage: "ghcr.io/opentofu/opentofu:latest",
}

return ctrl
Expand Down Expand Up @@ -936,6 +937,7 @@ var _ = Describe("Configuration Controller", func() {
kc: kfake.NewSimpleClientset(),
cache: cache.New(5*time.Minute, 10*time.Minute),
recorder: recorder,
BinaryPath: "/bin/opentofu",
DefaultExecutorCPULimit: "1",
DefaultExecutorCPURequest: "5m",
DefaultExecutorMemoryLimit: "1Gi",
Expand All @@ -946,7 +948,7 @@ var _ = Describe("Configuration Controller", func() {
InfracostsImage: "infracosts/infracost:latest",
ControllerNamespace: "default",
PolicyImage: "bridgecrew/checkov:2.0.1140",
TerraformImage: "hashicorp/terraform:1.1.9",
TerraformImage: "ghcr.io/opentofu/opentofu:latest",
}
ctrl.cache.SetDefault(cfgNamespace, fixtures.NewNamespace(cfgNamespace))
}
Expand Down Expand Up @@ -1426,7 +1428,7 @@ var _ = Describe("Configuration Controller", func() {

Expect(cc.List(context.TODO(), list, client.InNamespace(ctrl.ControllerNamespace))).ToNot(HaveOccurred())
Expect(len(list.Items)).To(Equal(1))
Expect(list.Items[0].Spec.Template.Spec.Containers[0].Image).To(Equal("hashicorp/terraform:test"))
Expect(list.Items[0].Spec.Template.Spec.Containers[0].Image).To(Equal("ghcr.io/opentofu/opentofu:test"))
})
})

Expand All @@ -1442,7 +1444,7 @@ var _ = Describe("Configuration Controller", func() {

Expect(cc.List(context.TODO(), list, client.InNamespace(ctrl.ControllerNamespace))).ToNot(HaveOccurred())
Expect(len(list.Items)).To(Equal(1))
Expect(list.Items[0].Spec.Template.Spec.Containers[0].Image).To(Equal("hashicorp/terraform:1.1.9"))
Expect(list.Items[0].Spec.Template.Spec.Containers[0].Image).To(Equal("ghcr.io/opentofu/opentofu:latest"))
})
})
})
Expand Down Expand Up @@ -2010,8 +2012,8 @@ terraform {

expected := []string{
"--comment=Executing Terraform",
"--command=/bin/terraform plan --var-file variables.tfvars.json -out=/run/plan.out -lock=false -no-color -input=false",
"--command=/bin/terraform show -json /run/plan.out > /run/tfplan.json",
"--command=/bin/opentofu plan --var-file variables.tfvars.json -out=/run/plan.out -lock=false -no-color -input=false",
"--command=/bin/opentofu show -json /run/plan.out > /run/tfplan.json",
"--command=/bin/cp /run/tfplan.json /run/plan.json",
"--command=/bin/gzip /run/plan.json",
"--command=/bin/mv /run/plan.json.gz /run/plan.json",
Expand Down Expand Up @@ -3293,7 +3295,7 @@ terraform {

expected := []string{
"--comment=Executing Terraform",
"--command=/bin/terraform apply --var-file variables.tfvars.json -lock=false -no-color -input=false -auto-approve",
"--command=/bin/opentofu apply --var-file variables.tfvars.json -lock=false -no-color -input=false -auto-approve",
"--on-error=/run/steps/terraform.failed",
"--on-success=/run/steps/terraform.complete",
}
Expand Down
1 change: 1 addition & 0 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ func New(cfg *rest.Config, config Config) (*Server, error) {
if err := (&configuration.Controller{
BackendTemplate: config.BackendTemplate,
BackoffLimit: config.BackoffLimit,
BinaryPath: config.BinaryPath,
ControllerJobLabels: jobLabels,
ControllerNamespace: config.Namespace,
DefaultExecutorCPULimit: config.ExecutorCPULimit,
Expand Down
2 changes: 2 additions & 0 deletions pkg/server/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ type Config struct {
BackendTemplate string
// BackoffLimit is the number of times we are willing to allow a job to fail
BackoffLimit int
// BinaryPath is the name of the binary to use to run the terraform commands
BinaryPath string
// ConfigurationThreshold is the max number of configurations we are willing
// to run at the same time
ConfigurationThreshold float64
Expand Down
9 changes: 6 additions & 3 deletions pkg/utils/jobs/jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ type Options struct {
// BackoffLimit is the number of times we are willing to allow a job to fail
// before we give up
BackoffLimit int
// BinaryPath is the name of the binary to use to run the terraform commands
BinaryPath string
// DefaultExecutorMemoryRequest is the default memory request for the executor
DefaultExecutorMemoryRequest string
// DefaultExecutorMemoryLimit is the default memory limit for the executor
Expand Down Expand Up @@ -81,8 +83,8 @@ type Options struct {
SaveTerraformState bool
// Template is the source for the job template if overridden by the controller
Template []byte
// TerraformImage is the image to use for the terraform jobs
TerraformImage string
// Image is the image to use for the terraform jobs
Image string
}

// Render is responsible for rendering the terraform configuration
Expand Down Expand Up @@ -214,6 +216,7 @@ func (r *Render) createTerraformFromTemplate(options Options, stage string) (*ba
terraformv1alpha1.ConfigurationStageLabel: stage,
terraformv1alpha1.ConfigurationUIDLabel: string(r.configuration.GetUID()),
}),
"BinaryPath": options.BinaryPath,
"DefaultExecutorMemoryRequest": options.DefaultExecutorMemoryRequest,
"DefaultExecutorMemoryLimit": options.DefaultExecutorMemoryLimit,
"DefaultExecutorCPURequest": options.DefaultExecutorCPURequest,
Expand Down Expand Up @@ -247,7 +250,7 @@ func (r *Render) createTerraformFromTemplate(options Options, stage string) (*ba
"Images": map[string]interface{}{
"Executor": options.ExecutorImage,
"Infracosts": options.InfracostsImage,
"Terraform": options.TerraformImage,
"Image": options.Image,
"Policy": options.PolicyImage,
},
"Secrets": map[string]interface{}{
Expand Down

0 comments on commit 24730ae

Please sign in to comment.