Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: introduce json format for inline module (#165) #283

Merged
merged 1 commit into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions apis/v1beta1/workspace_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ const (
VarFileSourceSecretKey VarFileSource = "SecretKey"
)

// A VarFileFormat specifies the format of a Terraform vars file.
// A FileFormat specifies the format of a Terraform file.
// +kubebuilder:validation:Enum=HCL;JSON
type VarFileFormat string
type FileFormat string

// Vars file formats.
var (
VarFileFormatHCL VarFileFormat = "HCL"
VarFileFormatJSON VarFileFormat = "JSON"
FileFormatHCL FileFormat = "HCL"
FileFormatJSON FileFormat = "JSON"
)

// A VarFile is a file containing many Terraform variables.
Expand All @@ -57,7 +57,7 @@ type VarFile struct {
// Format of this vars file.
// +kubebuilder:default=HCL
// +optional
Format *VarFileFormat `json:"format,omitempty"`
Format *FileFormat `json:"format,omitempty"`

// A ConfigMap key containing the vars file.
// +optional
Expand Down Expand Up @@ -108,9 +108,13 @@ type WorkspaceParameters struct {
// file. When the workspace's source is 'Remote' (the default) this can be
// any address supported by terraform init -from-module, for example a git
// repository or an S3 bucket. When the workspace's source is 'Inline' the
// content of a simple main.tf file may be written inline.
// content of a simple main.tf or main.tf.json file may be written inline.
Module string `json:"module"`

// Specifies the format of the inline Terraform content
// if Source is 'Inline'
InlineFormat FileFormat `json:"inlineFormat,omitempty"`

// Source of the root module of this workspace.
Source ModuleSource `json:"source"`

Expand Down
2 changes: 1 addition & 1 deletion apis/v1beta1/zz_generated.deepcopy.go

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

13 changes: 9 additions & 4 deletions internal/controller/workspace/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const (
errWriteCreds = "cannot write Terraform credentials"
errWriteGitCreds = "cannot write .git-credentials to /tmp dir"
errWriteConfig = "cannot write Terraform configuration " + tfConfig
errWriteMain = "cannot write Terraform configuration " + tfMain
errWriteMain = "cannot write Terraform configuration "
errWriteBackend = "cannot write Terraform configuration " + tfBackendFile
errInit = "cannot initialize Terraform configuration"
errWorkspace = "cannot select Terraform workspace"
Expand All @@ -87,6 +87,7 @@ const (
// TODO(negz): Make the Terraform binary path and work dir configurable.
tfPath = "terraform"
tfMain = "main.tf"
tfMainJSON = "main.tf.json"
tfConfig = "crossplane-provider-config.tf"
tfBackendFile = "crossplane.remote.tfbackend"
)
Expand Down Expand Up @@ -249,8 +250,12 @@ func (c *connector) Connect(ctx context.Context, mg resource.Managed) (managed.E
}

case v1beta1.ModuleSourceInline:
if err := c.fs.WriteFile(filepath.Join(dir, tfMain), []byte(cr.Spec.ForProvider.Module), 0600); err != nil {
return nil, errors.Wrap(err, errWriteMain)
fn := tfMain
if cr.Spec.ForProvider.InlineFormat == v1beta1.FileFormatJSON {
fn = tfMainJSON
}
if err := c.fs.WriteFile(filepath.Join(dir, fn), []byte(cr.Spec.ForProvider.Module), 0600); err != nil {
return nil, errors.Wrap(err, errWriteMain+fn)
}
}

Expand Down Expand Up @@ -481,7 +486,7 @@ func (c *external) options(ctx context.Context, p v1beta1.WorkspaceParameters) (

for _, vf := range p.VarFiles {
fmt := terraform.HCL
if vf.Format != nil && *vf.Format == v1beta1.VarFileFormatJSON {
if vf.Format != nil && *vf.Format == v1beta1.FileFormatJSON {
fmt = terraform.JSON
}

Expand Down
42 changes: 39 additions & 3 deletions internal/controller/workspace/workspace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,43 @@ func TestConnect(t *testing.T) {
},
},
},
want: errors.Wrap(errBoom, errWriteMain),
want: errors.Wrap(errBoom, errWriteMain+tfMain),
},
"WriteMainJsonError": {
reason: "We should return any error encountered while writing our main.tf file",
fields: fields{
kube: &test.MockClient{
MockGet: test.NewMockGetFn(nil),
},
usage: resource.TrackerFn(func(_ context.Context, _ resource.Managed) error { return nil }),
fs: afero.Afero{
Fs: &ErrFs{
Fs: afero.NewMemMapFs(),
errs: map[string]error{filepath.Join(tfDir, string(uid), tfMainJSON): errBoom},
},
},
terraform: func(_ string, _ bool, _ ...string) tfclient {
return &MockTf{
MockInit: func(ctx context.Context, o ...terraform.InitOption) error { return nil },
}
},
},
args: args{
mg: &v1beta1.Workspace{
ObjectMeta: metav1.ObjectMeta{UID: uid},
Spec: v1beta1.WorkspaceSpec{
ResourceSpec: xpv1.ResourceSpec{
ProviderConfigReference: &xpv1.Reference{},
},
ForProvider: v1beta1.WorkspaceParameters{
Module: "I'm JSON!",
Source: v1beta1.ModuleSourceInline,
InlineFormat: v1beta1.FileFormatJSON,
},
},
},
},
want: errors.Wrap(errBoom, errWriteMain+tfMainJSON),
},
"TerraformInitError": {
reason: "We should return any error encountered while initializing Terraform",
Expand Down Expand Up @@ -1298,7 +1334,7 @@ func TestCreate(t *testing.T) {
{
Source: v1beta1.VarFileSourceSecretKey,
SecretKeyReference: &v1beta1.KeyReference{},
Format: &v1beta1.VarFileFormatJSON,
Format: &v1beta1.FileFormatJSON,
},
},
},
Expand Down Expand Up @@ -1483,7 +1519,7 @@ func TestDelete(t *testing.T) {
{
Source: v1beta1.VarFileSourceSecretKey,
SecretKeyReference: &v1beta1.KeyReference{},
Format: &v1beta1.VarFileFormatJSON,
Format: &v1beta1.FileFormatJSON,
},
},
},
Expand Down
10 changes: 9 additions & 1 deletion package/crds/tf.upbound.io_workspaces.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,21 @@ spec:
items:
type: string
type: array
inlineFormat:
description: |-
Specifies the format of the inline Terraform content
if Source is 'Inline'
enum:
- HCL
- JSON
type: string
module:
description: |-
The root module of this workspace; i.e. the module containing its main.tf
file. When the workspace's source is 'Remote' (the default) this can be
any address supported by terraform init -from-module, for example a git
repository or an S3 bucket. When the workspace's source is 'Inline' the
content of a simple main.tf file may be written inline.
content of a simple main.tf or main.tf.json file may be written inline.
type: string
planArgs:
description: Arguments to be included in the terraform plan CLI
Expand Down
Loading