From 9ba4ba545e482e6d17222adef466c54a6b6a0010 Mon Sep 17 00:00:00 2001 From: sternik <147771+sternik@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:05:57 +0200 Subject: [PATCH] feat: add support to use custom image name in GCP (#74) --- docs/index.md | 2 +- docs/resources/template.md | 36 +++++++++++++++++++ examples/provider/provider.tf | 2 +- .../imagefactory_template/resource.tf | 27 ++++++++++++++ imagefactory/imagetemplate/schema.go | 24 +++++++++++++ imagefactory/imagetemplate/structures.go | 18 ++++++++++ pkg/graphql/graphql.go | 11 ++++++ pkg/graphql/schema.graphql | 24 +++++++++++++ 8 files changed, 142 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index acb858b..1004f09 100644 --- a/docs/index.md +++ b/docs/index.md @@ -34,7 +34,7 @@ terraform { required_providers { imagefactory = { source = "nordcloud/imagefactory" - version = "1.10.0" + version = "1.11.0" } } } diff --git a/docs/resources/template.md b/docs/resources/template.md index 7131321..a2d05a0 100644 --- a/docs/resources/template.md +++ b/docs/resources/template.md @@ -269,6 +269,33 @@ resource "imagefactory_template" "exoscale_template" { output "template" { value = imagefactory_template.exoscale_template } + +# GCP Template + +data "imagefactory_distribution" "ubuntu22" { + name = "Ubuntu Server 22.04 LTS" + cloud_provider = "GCP" +} + +resource "imagefactory_template" "gcp_template" { + name = "Ubuntu2204" + description = "Ubuntu Server 22.04 on GCP" + cloud_provider = "GCP" + distribution_id = data.imagefactory_distribution.ubuntu22.id + config { + gcp { + custom_image_name = "ubuntu-22-04-prod-1-3" + } + notifications { + type = "WEB_HOOK" + uri = "https://webhook.call.api.address" + } + } +} + +output "template" { + value = imagefactory_template.gcp_template +} ``` @@ -301,6 +328,7 @@ Optional: - `cloud_account_ids` (List of String) - `disable_cyclical_rebuilds` (Boolean) Disable cyclical rebuilds. Cyclical rebuilds are rebuilds that are triggered automatically by ImageFactory when the source image is updated or when there are security updates available for the packages installed in the image. If cyclical rebuilds are disabled, the template will not be rebuilt automatically and the user will have to trigger the rebuild manually. Default value is set to false. - `exoscale` (Block List) (see [below for nested schema](#nestedblock--config--exoscale)) +- `gcp` (Block List) (see [below for nested schema](#nestedblock--config--gcp)) - `notifications` (Block List) (see [below for nested schema](#nestedblock--config--notifications)) - `scope` (String) - `tags` (Block List) (see [below for nested schema](#nestedblock--config--tags)) @@ -382,6 +410,14 @@ Required: - `zone` (String) + +### Nested Schema for `config.gcp` + +Optional: + +- `custom_image_name` (String) The name of the custom image. Must be a valid custom image name. The name must start with a lowercase letter, followed by a dash or a lowercase letter or a digit. The name must end with a lowercase letter or a digit. The name must be between 3 and 45 characters long. + + ### Nested Schema for `config.notifications` diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index ed04e64..90b9b5a 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -7,7 +7,7 @@ terraform { required_providers { imagefactory = { source = "nordcloud/imagefactory" - version = "1.10.0" + version = "1.11.0" } } } diff --git a/examples/resources/imagefactory_template/resource.tf b/examples/resources/imagefactory_template/resource.tf index b14229d..fdd626a 100644 --- a/examples/resources/imagefactory_template/resource.tf +++ b/examples/resources/imagefactory_template/resource.tf @@ -254,3 +254,30 @@ resource "imagefactory_template" "exoscale_template" { output "template" { value = imagefactory_template.exoscale_template } + +# GCP Template + +data "imagefactory_distribution" "ubuntu22" { + name = "Ubuntu Server 22.04 LTS" + cloud_provider = "GCP" +} + +resource "imagefactory_template" "gcp_template" { + name = "Ubuntu2204" + description = "Ubuntu Server 22.04 on GCP" + cloud_provider = "GCP" + distribution_id = data.imagefactory_distribution.ubuntu22.id + config { + gcp { + custom_image_name = "ubuntu-22-04-prod-1-3" + } + notifications { + type = "WEB_HOOK" + uri = "https://webhook.call.api.address" + } + } +} + +output "template" { + value = imagefactory_template.gcp_template +} diff --git a/imagefactory/imagetemplate/schema.go b/imagefactory/imagetemplate/schema.go index 210a0bd..025aa73 100644 --- a/imagefactory/imagetemplate/schema.go +++ b/imagefactory/imagetemplate/schema.go @@ -192,6 +192,25 @@ var exoscaleTemplateConfigResource = &schema.Resource{ }, } +var customImageNameValidationDescription = "Must be a valid custom image name. " + + "The name must start with a lowercase letter, followed by a dash or a lowercase letter or a digit. " + + "The name must end with a lowercase letter or a digit. " + + "The name must be between 3 and 45 characters long." + +var gcpTemplateConfigResource = &schema.Resource{ + Schema: map[string]*schema.Schema{ + "custom_image_name": { + Type: schema.TypeString, + Optional: true, + Description: "The name of the custom image. " + customImageNameValidationDescription, + ValidateFunc: validation.StringMatch( + regexp.MustCompile(`^[a-z]([-a-z0-9]*[a-z0-9]){2,44}$`), + customImageNameValidationDescription, + ), + }, + }, +} + var templateComponentResource = &schema.Resource{ Schema: map[string]*schema.Schema{ "id": { @@ -252,6 +271,11 @@ var templateConfigResource = &schema.Resource{ Optional: true, Elem: exoscaleTemplateConfigResource, }, + "gcp": { + Type: schema.TypeList, + Optional: true, + Elem: gcpTemplateConfigResource, + }, "build_components": { Type: schema.TypeList, Optional: true, diff --git a/imagefactory/imagetemplate/structures.go b/imagefactory/imagetemplate/structures.go index 88e2727..bc84278 100644 --- a/imagefactory/imagetemplate/structures.go +++ b/imagefactory/imagetemplate/structures.go @@ -181,6 +181,23 @@ func expandTemplateExoscaleConfig(in []interface{}) *graphql.NewTemplateExoscale } } +func expandTemplateGcpConfig(in []interface{}) *graphql.NewTemplateGCPConfig { + if len(in) == 0 { + return nil + } + + var imageName graphql.String + + m := in[0].(map[string]interface{}) + if m["custom_image_name"] != nil || m["custom_image_name"].(string) != "" { + imageName = graphql.String(m["custom_image_name"].(string)) + } + + return &graphql.NewTemplateGCPConfig{ + CustomImageName: &imageName, + } +} + func expandTemplateConfig(in []interface{}) (*graphql.NewTemplateConfig, error) { if len(in) == 0 { return &graphql.NewTemplateConfig{}, nil @@ -198,6 +215,7 @@ func expandTemplateConfig(in []interface{}) (*graphql.NewTemplateConfig, error) Aws: awsCfg, Azure: expandTemplateAzureConfig(m["azure"].([]interface{})), Exoscale: expandTemplateExoscaleConfig(m["exoscale"].([]interface{})), + Gcp: expandTemplateGcpConfig(m["gcp"].([]interface{})), BuildComponents: expandTemplateComponents(m["build_components"].([]interface{})), TestComponents: expandTemplateComponents(m["test_components"].([]interface{})), Notifications: expandTemplateNotifications(m["notifications"].([]interface{})), diff --git a/pkg/graphql/graphql.go b/pkg/graphql/graphql.go index 9d82562..1023445 100644 --- a/pkg/graphql/graphql.go +++ b/pkg/graphql/graphql.go @@ -3778,6 +3778,7 @@ type NewTemplateConfig struct { CloudAccountIds *[]String `json:"cloudAccountIds,omitempty"` DisableCyclicalRebuilds *Boolean `json:"disableCyclicalRebuilds,omitempty"` Exoscale *NewTemplateExoscaleConfig `json:"exoscale,omitempty"` + Gcp *NewTemplateGCPConfig `json:"gcp,omitempty"` ImageRetainCount *Int `json:"imageRetainCount,omitempty"` Notifications *[]NewNotification `json:"notifications,omitempty"` Scope *Scope `json:"scope,omitempty"` @@ -3789,6 +3790,10 @@ type NewTemplateExoscaleConfig struct { Zone *String `json:"zone,omitempty"` } +type NewTemplateGCPConfig struct { + CustomImageName *String `json:"customImageName,omitempty"` +} + type NewUefiKey struct { VariableName String `json:"variableName"` } @@ -4155,6 +4160,7 @@ type ImageBuildDetails struct { PackageInventory *String `json:"packageInventory,omitempty"` ResultImageId *String `json:"resultImageId,omitempty"` ResultImageUri *String `json:"resultImageUri,omitempty"` + Sbom *String `json:"sbom,omitempty"` SourceDistribution *SourceDistribution `json:"sourceDistribution,omitempty"` SourceImage *String `json:"sourceImage,omitempty"` Tags *[]Tag `json:"tags,omitempty"` @@ -4385,6 +4391,7 @@ type TemplateConfig struct { CloudAccountIds *[]String `json:"cloudAccountIds,omitempty"` DisableCyclicalRebuilds *Boolean `json:"disableCyclicalRebuilds,omitempty"` Exoscale *TemplateExoscaleConfig `json:"exoscale,omitempty"` + Gcp *TemplateGCPConfig `json:"gcp,omitempty"` ImageRetainCount *Int `json:"imageRetainCount,omitempty"` Notifications *[]Notification `json:"notifications,omitempty"` Scope *Scope `json:"scope,omitempty"` @@ -4396,6 +4403,10 @@ type TemplateExoscaleConfig struct { Zone *String `json:"zone,omitempty"` } +type TemplateGCPConfig struct { + CustomImageName *String `json:"customImageName,omitempty"` +} + type TemplateResults struct { Count Int `json:"count"` Pages Int `json:"pages"` diff --git a/pkg/graphql/schema.graphql b/pkg/graphql/schema.graphql index 5c83347..15d1ca9 100644 --- a/pkg/graphql/schema.graphql +++ b/pkg/graphql/schema.graphql @@ -731,6 +731,7 @@ type ImageBuildDetails { changeLog: String compliance: Compliance packageInventory: String + sbom: String resultImageId: String resultImageUri: String buildTimeSec: Int @@ -1042,6 +1043,10 @@ type TemplateExoscaleConfig { zone: String } +type TemplateGCPConfig { + customImageName: String +} + type TemplateConfig { buildComponents: [TemplateComponent!] testComponents: [TemplateComponent!] @@ -1053,6 +1058,7 @@ type TemplateConfig { aws: TemplateAWSConfig azure: TemplateAZUREConfig exoscale: TemplateExoscaleConfig + gcp: TemplateGCPConfig """ cloudAccountIds contains a list of Cloud Account IDs to which we will distribute the image @@ -1217,6 +1223,19 @@ input NewTemplateExoscaleConfig { zone: String } +input NewTemplateGCPConfig { + """ + `customImageName` specifies the name of the image to be created in Google Cloud Platform. + + The name must be unique within the project and adhere to the following restrictions: + * Must be 3-45 characters long. + * Must start with a lowercase letter, followed by up to 44 lowercase letters, numbers, or dashes. + + ImageFactory will append a timestamp suffix to the image name in the format `custom-image-name-yyyymmddhhmmssmmm`. + """ + customImageName: String +} + """ NewTemplateConfig defines the image customization. @@ -1256,6 +1275,11 @@ input NewTemplateConfig { """ exoscale: NewTemplateExoscaleConfig + """ + gcp defines additional configuration for the Google Cloud provider. This is optional and can be used only for GOOGLE CLOUD template. + """ + gcp: NewTemplateGCPConfig + """ cloudAccountIds defines a list of Cloud Account IDs to which we will distribute the image. """