Skip to content

Commit

Permalink
Adds CRD fields: property and required
Browse files Browse the repository at this point in the history
  • Loading branch information
Nick Schuch committed Jul 21, 2023
1 parent 0be2e66 commit e833e5d
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 16 deletions.
17 changes: 17 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM golang:1.19-alpine3.17 as build

RUN apk add make gcc musl-dev

WORKDIR /go/src/github.com/previousnext/terraform-provider-k8s
COPY . /go/src/github.com/previousnext/terraform-provider-k8s

RUN go build -ldflags "-linkmode external -extldflags -static" -o terraform-provider-k8s

FROM hashicorp/terraform:0.14.8 as run

RUN apk add bash

RUN mkdir -p /root/.terraform.d/plugins

COPY --from=build /go/src/github.com/previousnext/terraform-provider-k8s/terraform-provider-k8s /root/.terraform.d/plugins/registry.terraform.io/previousnext/k8s/99.0.0/linux_amd64/terraform-provider-k8s_v99.0.0
RUN chmod +x /root/.terraform.d/plugins/registry.terraform.io/*/*/*/linux_amd64/terraform-provider-*
30 changes: 19 additions & 11 deletions internal/resources/apiextensions/v1beta1/crd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,25 @@ package crd

import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/previousnext/terraform-provider-k8s/internal/interfaceutils"
"github.com/previousnext/terraform-provider-k8s/internal/resources/apiextensions/v1beta1/crd/names"
"github.com/previousnext/terraform-provider-k8s/internal/resources/apiextensions/v1beta1/crd/property"
"github.com/previousnext/terraform-provider-k8s/internal/resources/apiextensions/v1beta1/crd/required"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Generate the ServiceAccount.
func Generate(d *schema.ResourceData) (apiextensionsv1.CustomResourceDefinition, error) {
var (
name = d.Get(FieldName).(string)
rawLabels = d.Get(FieldLabels).(map[string]interface{})
group = d.Get(FieldGroup).(string)
version = d.Get(FieldVersion).(string)
scope = d.Get(FieldScope).(string)
rawNames = d.Get(FieldNames).([]interface{})
name = d.Get(FieldName).(string)
rawLabels = d.Get(FieldLabels).(map[string]interface{})
group = d.Get(FieldGroup).(string)
version = d.Get(FieldVersion).(string)
scope = d.Get(FieldScope).(string)
rawNames = d.Get(FieldNames).([]interface{})
rawProperties = d.Get(FieldProperty).(*schema.Set).List()
rawRequired = d.Get(FieldRequired).([]interface{})
)

crd := apiextensionsv1.CustomResourceDefinition{
Expand All @@ -32,8 +35,13 @@ func Generate(d *schema.ResourceData) (apiextensionsv1.CustomResourceDefinition,
Name: version,
Served: true,
Storage: true,
// @todo, Determine better approach for schema.
Schema: &apiextensionsv1.CustomResourceValidation{},
Schema: &apiextensionsv1.CustomResourceValidation{
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
Properties: property.Expand(rawProperties),
Required: required.Expand(rawRequired),
Type: "object",
},
},
Subresources: &apiextensionsv1.CustomResourceSubresources{
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
},
Expand Down
37 changes: 37 additions & 0 deletions internal/resources/apiextensions/v1beta1/crd/property/expand.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package property

import (
"k8s.io/utils/pointer"

apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)

// Expand will return a structured object.
func Expand(in []interface{}) map[string]apiextensionsv1.JSONSchemaProps {
if len(in) == 0 {
return nil
}

vars := make(map[string]apiextensionsv1.JSONSchemaProps, len(in))

for _, v := range in {
value := v.(map[string]interface{})

prop := apiextensionsv1.JSONSchemaProps{}

if val, ok := value[FieldType]; ok && val != "" {
prop.Type = val.(string)
}

if val, ok := value[FieldPreserveUnknownFields]; ok && val == true {
prop.XPreserveUnknownFields = pointer.Bool(true)
}

if val, ok := value[FieldName]; ok && val != "" {
vars[val.(string)] = prop
}
}

return vars
}

39 changes: 39 additions & 0 deletions internal/resources/apiextensions/v1beta1/crd/property/fields.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package property

import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

const (
// FieldName is a field identifier.
FieldName = "name"
// FieldType is a field identifier.
FieldType = "type"
// FieldPreserveUnknownFields is a field identifier.
FieldPreserveUnknownFields = "preserve_unknown_fields"
)

// Fields returns the fields for this package.
func Fields() *schema.Schema {
return &schema.Schema{
Description: "Environment variables which can be set for a container",
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
FieldName: {
Type: schema.TypeString,
Required: true,
},
FieldType: {
Type: schema.TypeString,
Required: true,
},
FieldPreserveUnknownFields: {
Type: schema.TypeBool,
Optional: true,
},
},
},
}
}
29 changes: 29 additions & 0 deletions internal/resources/apiextensions/v1beta1/crd/property/flatten.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package property

import (
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)

// Flatten structured object into unstructured.
func Flatten(in map[string]apiextensionsv1.JSONSchemaProps) []interface{} {
flattened := make([]interface{}, 0)

for name, value := range in {
row := map[string]interface{}{}

row[FieldName] = name

if value.Type != "" {
row[FieldType] = value.Type
}

if value.XPreserveUnknownFields != nil {
row[FieldPreserveUnknownFields] = *value.XPreserveUnknownFields
}

flattened = append(flattened, row)
}

return flattened
}

6 changes: 6 additions & 0 deletions internal/resources/apiextensions/v1beta1/crd/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/previousnext/terraform-provider-k8s/internal/resources/apiextensions/v1beta1/crd/names"
"github.com/previousnext/terraform-provider-k8s/internal/resources/apiextensions/v1beta1/crd/property"
"github.com/previousnext/terraform-provider-k8s/internal/terraform/config"
"github.com/previousnext/terraform-provider-k8s/internal/terraform/id"
)
Expand Down Expand Up @@ -47,5 +48,10 @@ func Read(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagn
d.Set(FieldScope, crd.Spec.Scope)
d.Set(FieldNames, names.Flatten(crd.Spec.Names))

if len(crd.Spec.Versions) > 0 {
d.Set(FieldProperty, property.Flatten(crd.Spec.Versions[0].Schema.OpenAPIV3Schema.Properties))
d.Set(FieldRequired, crd.Spec.Versions[0].Schema.OpenAPIV3Schema.Required)
}

return diags
}
12 changes: 12 additions & 0 deletions internal/resources/apiextensions/v1beta1/crd/required/expand.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package required

// Expand will return a structured object.
func Expand(s []interface{}) []string {
result := make([]string, len(s))

for k, v := range s {
result[k] = v.(string)
}

return result
}
16 changes: 16 additions & 0 deletions internal/resources/apiextensions/v1beta1/crd/required/fields.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package required

import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// Fields returns the fields for this package.
func Fields() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
}
}
14 changes: 11 additions & 3 deletions internal/resources/apiextensions/v1beta1/crd/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package crd

import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/previousnext/terraform-provider-k8s/internal/resources/apiextensions/v1beta1/crd/property"
"github.com/previousnext/terraform-provider-k8s/internal/resources/apiextensions/v1beta1/crd/required"

"github.com/previousnext/terraform-provider-k8s/internal/resources/apiextensions/v1beta1/crd/names"
)
Expand All @@ -21,6 +23,10 @@ const (
FieldScope = "scope"
// FieldNames is a field identifier.
FieldNames = "names"
// FieldProperty is a field identifier.
FieldProperty = "property"
// FieldRequired is a field identifier.
FieldRequired = "required"
)

// Resource returns this packages Resource and Fields.
Expand All @@ -32,11 +38,11 @@ func Resource() *schema.Resource {
DeleteContext: Delete,

Schema: map[string]*schema.Schema{
FieldName: &schema.Schema{
FieldName: {
Type: schema.TypeString,
Required: true,
},
FieldLabels: &schema.Schema{
FieldLabels: {
Type: schema.TypeMap,
Optional: true,
},
Expand All @@ -52,7 +58,9 @@ func Resource() *schema.Resource {
Type: schema.TypeString,
Required: true,
},
FieldNames: names.Fields(),
FieldNames: names.Fields(),
FieldProperty: property.Fields(),
FieldRequired: required.Fields(),
},
}
}
12 changes: 10 additions & 2 deletions internal/resources/apiextensions/v1beta1/crd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,23 @@ func Update(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Dia

conn := m.(*config.Client)

crd, err := Generate(d)
c, err := Generate(d)
if err != nil {
return diag.FromErr(err)
}

_, err = conn.APIExtensions().ApiextensionsV1().CustomResourceDefinitions().Update(ctx, &crd, metav1.UpdateOptions{})
crd, err := conn.APIExtensions().ApiextensionsV1().CustomResourceDefinitions().Get(ctx, c.ObjectMeta.Name, metav1.GetOptions{})
if err != nil {
return diag.FromErr(err)
}

crd.Spec = c.Spec

_, err = conn.APIExtensions().ApiextensionsV1().CustomResourceDefinitions().Update(ctx, crd, metav1.UpdateOptions{})
if err != nil {
return diag.FromErr(err)
}

return diags
}

0 comments on commit e833e5d

Please sign in to comment.