Skip to content

Commit

Permalink
[FEATURE] - Switching to Opentofu (#1550)
Browse files Browse the repository at this point in the history
* [FEATURE] - Switching to Opentofu

Currently we are using the hashicorp image and binary, this PR changes the default implementation to opentofu

* chore: updating the unit tests

* chore: fixing up the reference to the binary

* chore: changing the iamge to use in the helm chart
  • Loading branch information
gambol99 authored Nov 15, 2024
1 parent a5df2ac commit 6139c2f
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 23 deletions.
2 changes: 1 addition & 1 deletion charts/terranetes-controller/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ controller:
# Configuration for the images used by the jobs
images:
# is the default image to use for terraform operations
terraform: hashicorp/terraform:1.5.7
terraform: ghcr.io/opentofu/opentofu:1.8.5
# image to use for infracost
infracost: infracost/infracost:ci-0.10.35
# policy is image for policy
Expand Down
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", "/usr/local/bin/tofu", "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,
DefaultExecutorCPULimit: c.DefaultExecutorCPULimit,
DefaultExecutorCPURequest: c.DefaultExecutorCPURequest,
DefaultExecutorMemoryLimit: c.DefaultExecutorMemoryLimit,
Expand All @@ -1267,7 +1269,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: "/usr/local/bin/tofu",
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: "/usr/local/bin/tofu",
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=/usr/local/bin/tofu plan --var-file variables.tfvars.json -out=/run/plan.out -lock=false -no-color -input=false",
"--command=/usr/local/bin/tofu 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=/usr/local/bin/tofu 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 6139c2f

Please sign in to comment.