From 0a255df1ca89fc7c3f2189444847b39533a070b1 Mon Sep 17 00:00:00 2001 From: Sanne Raymaekers Date: Wed, 4 Oct 2023 12:16:14 +0200 Subject: [PATCH] cloudapi/v2: add all existing customizations to openapi spec --- internal/cloudapi/v2/compose.go | 185 ++++++++++++ internal/cloudapi/v2/compose_test.go | 83 ++++- internal/cloudapi/v2/openapi.v2.gen.go | 401 ++++++++++++++++--------- internal/cloudapi/v2/openapi.v2.yml | 169 +++++++++++ test/cases/api.sh | 20 ++ test/cases/api/aws.sh | 1 + test/cases/api/azure.sh | 1 + test/cases/api/common/common.sh | 17 ++ test/cases/api/common/s3.sh | 2 + test/cases/api/gcp.sh | 1 + test/cases/api/oci.sh | 1 + 11 files changed, 743 insertions(+), 138 deletions(-) diff --git a/internal/cloudapi/v2/compose.go b/internal/cloudapi/v2/compose.go index b45ba771e..50147f78d 100644 --- a/internal/cloudapi/v2/compose.go +++ b/internal/cloudapi/v2/compose.go @@ -292,6 +292,191 @@ func (request *ComposeRequest) GetBlueprintWithCustomizations() (blueprint.Bluep bp.Customizations.Repositories = repoCustomizations } } + + if request.Customizations.Hostname != nil { + if bp.Customizations == nil { + bp.Customizations = &blueprint.Customizations{ + Hostname: request.Customizations.Hostname, + } + } else { + bp.Customizations.Hostname = request.Customizations.Hostname + } + } + + if request.Customizations.Kernel != nil { + kernel := &blueprint.KernelCustomization{} + if request.Customizations.Kernel.Name != nil { + kernel.Name = *request.Customizations.Kernel.Name + } + if request.Customizations.Kernel.Append != nil { + kernel.Append = *request.Customizations.Kernel.Append + } + + if bp.Customizations == nil { + bp.Customizations = &blueprint.Customizations{ + Kernel: kernel, + } + } else { + bp.Customizations.Kernel = kernel + } + } + + if request.Customizations.Sshkey != nil { + keys := []blueprint.SSHKeyCustomization{} + for _, key := range *request.Customizations.Sshkey { + keys = append(keys, blueprint.SSHKeyCustomization{ + User: key.User, + Key: key.Key, + }) + } + if bp.Customizations == nil { + bp.Customizations = &blueprint.Customizations{ + SSHKey: keys, + } + } else { + bp.Customizations.SSHKey = keys + } + } + + if request.Customizations.Group != nil { + groups := []blueprint.GroupCustomization{} + for _, group := range *request.Customizations.Group { + groups = append(groups, blueprint.GroupCustomization{ + Name: group.Name, + GID: group.Gid, + }) + } + + if bp.Customizations == nil { + bp.Customizations = &blueprint.Customizations{ + Group: groups, + } + } else { + bp.Customizations.Group = groups + } + } + + if request.Customizations.Timezone != nil { + tz := &blueprint.TimezoneCustomization{ + Timezone: request.Customizations.Timezone.Timezone, + } + + if request.Customizations.Timezone.Ntpservers != nil { + tz.NTPServers = append(tz.NTPServers, *request.Customizations.Timezone.Ntpservers...) + } + + if bp.Customizations == nil { + bp.Customizations = &blueprint.Customizations{ + Timezone: tz, + } + } else { + bp.Customizations.Timezone = tz + } + } + + if request.Customizations.Locale != nil { + locale := &blueprint.LocaleCustomization{ + Keyboard: request.Customizations.Locale.Keyboard, + } + + if request.Customizations.Locale.Languages != nil { + locale.Languages = append(locale.Languages, *request.Customizations.Locale.Languages...) + } + + if bp.Customizations == nil { + bp.Customizations = &blueprint.Customizations{ + Locale: locale, + } + } else { + bp.Customizations.Locale = locale + } + } + + if request.Customizations.Firewall != nil { + firewall := &blueprint.FirewallCustomization{} + + if request.Customizations.Firewall.Ports != nil { + firewall.Ports = append(firewall.Ports, *request.Customizations.Firewall.Ports...) + } + if request.Customizations.Firewall.Services != nil { + enabled := []string{} + if request.Customizations.Firewall.Services.Enabled != nil { + enabled = append(enabled, *request.Customizations.Firewall.Services.Enabled...) + } + disabled := []string{} + if request.Customizations.Firewall.Services.Disabled != nil { + disabled = append(disabled, *request.Customizations.Firewall.Services.Disabled...) + } + firewall.Services = &blueprint.FirewallServicesCustomization{ + Enabled: enabled, + Disabled: disabled, + } + } + + if bp.Customizations == nil { + bp.Customizations = &blueprint.Customizations{ + Firewall: firewall, + } + } else { + bp.Customizations.Firewall = firewall + } + } + + if request.Customizations.InstallationDevice != nil { + if bp.Customizations == nil { + bp.Customizations = &blueprint.Customizations{ + InstallationDevice: *request.Customizations.InstallationDevice, + } + } else { + bp.Customizations.InstallationDevice = *request.Customizations.InstallationDevice + } + } + + if request.Customizations.Fdo != nil { + fdo := &blueprint.FDOCustomization{} + if request.Customizations.Fdo.DiunPubKeyHash != nil { + fdo.DiunPubKeyHash = *request.Customizations.Fdo.DiunPubKeyHash + } + if request.Customizations.Fdo.DiunPubKeyInsecure != nil { + fdo.DiunPubKeyInsecure = *request.Customizations.Fdo.DiunPubKeyInsecure + } + if request.Customizations.Fdo.DiunPubKeyRootCerts != nil { + fdo.DiunPubKeyRootCerts = *request.Customizations.Fdo.DiunPubKeyRootCerts + } + if request.Customizations.Fdo.ManufacturingServerUrl != nil { + fdo.ManufacturingServerURL = *request.Customizations.Fdo.ManufacturingServerUrl + } + + if bp.Customizations == nil { + bp.Customizations = &blueprint.Customizations{ + FDO: fdo, + } + } else { + bp.Customizations.FDO = fdo + } + } + + if request.Customizations.Ignition != nil { + ignition := &blueprint.IgnitionCustomization{} + if request.Customizations.Ignition.Embedded != nil { + ignition.Embedded = &blueprint.EmbeddedIgnitionCustomization{ + Config: request.Customizations.Ignition.Embedded.Config, + } + } + if request.Customizations.Ignition.Firstboot != nil { + ignition.FirstBoot = &blueprint.FirstBootIgnitionCustomization{ + ProvisioningURL: request.Customizations.Ignition.Firstboot.Url, + } + } + if bp.Customizations == nil { + bp.Customizations = &blueprint.Customizations{ + Ignition: ignition, + } + } else { + bp.Customizations.Ignition = ignition + } + } + return bp, nil } diff --git a/internal/cloudapi/v2/compose_test.go b/internal/cloudapi/v2/compose_test.go index febc1e15a..4fc4daf7a 100644 --- a/internal/cloudapi/v2/compose_test.go +++ b/internal/cloudapi/v2/compose_test.go @@ -87,6 +87,47 @@ func TestGetBlueprintWithCustomizations(t *testing.T) { Enabled: common.ToPtr(true), }, }, + Firewall: &FirewallCustomization{ + Ports: common.ToPtr([]string{ + "22/tcp", + }), + }, + Hostname: common.ToPtr("hostname"), + InstallationDevice: common.ToPtr("/dev/sda"), + Kernel: &Kernel{ + Append: common.ToPtr("nosmt=force"), + Name: common.ToPtr("kernel-debug"), + }, + Locale: &Locale{ + Keyboard: common.ToPtr("us"), + Languages: common.ToPtr([]string{ + "en_US.UTF-8", + }), + }, + Fdo: &FDO{ + DiunPubKeyHash: common.ToPtr("pubkeyhash"), + DiunPubKeyInsecure: common.ToPtr("pubkeyinsecure"), + DiunPubKeyRootCerts: common.ToPtr("pubkeyrootcerts"), + ManufacturingServerUrl: common.ToPtr("serverurl"), + }, + Ignition: &Ignition{ + Firstboot: &IgnitionFirstboot{ + Url: "provisioning-url.local", + }, + }, + Sshkey: &[]SSHKey{ + { + Key: "key", + User: "user", + }, + }, + Timezone: &Timezone{ + Timezone: common.ToPtr("US/Eastern"), + Ntpservers: common.ToPtr([]string{ + "0.north-america.pool.ntp.org", + "1.north-america.pool.ntp.org", + }), + }, }} // Construct the expected blueprint result @@ -152,8 +193,48 @@ func TestGetBlueprintWithCustomizations(t *testing.T) { GPGCheck: common.ToPtr(true), }, }, + Firewall: &blueprint.FirewallCustomization{ + Ports: []string{ + "22/tcp", + }, + }, + Hostname: common.ToPtr("hostname"), + InstallationDevice: "/dev/sda", + Kernel: &blueprint.KernelCustomization{ + Append: "nosmt=force", + Name: "kernel-debug", + }, + Locale: &blueprint.LocaleCustomization{ + Keyboard: common.ToPtr("us"), + Languages: []string{ + "en_US.UTF-8", + }, + }, + FDO: &blueprint.FDOCustomization{ + DiunPubKeyHash: "pubkeyhash", + DiunPubKeyInsecure: "pubkeyinsecure", + DiunPubKeyRootCerts: "pubkeyrootcerts", + ManufacturingServerURL: "serverurl", + }, + Ignition: &blueprint.IgnitionCustomization{ + FirstBoot: &blueprint.FirstBootIgnitionCustomization{ + ProvisioningURL: "provisioning-url.local", + }, + }, + SSHKey: []blueprint.SSHKeyCustomization{ + { + Key: "key", + User: "user", + }, + }, + Timezone: &blueprint.TimezoneCustomization{ + Timezone: common.ToPtr("US/Eastern"), + NTPServers: []string{ + "0.north-america.pool.ntp.org", + "1.north-america.pool.ntp.org", + }, + }, } - bp, err = cr.GetBlueprintWithCustomizations() require.Nil(t, err) assert.Equal(t, bp, expected) diff --git a/internal/cloudapi/v2/openapi.v2.gen.go b/internal/cloudapi/v2/openapi.v2.gen.go index de31d32e4..d76523e6a 100644 --- a/internal/cloudapi/v2/openapi.v2.gen.go +++ b/internal/cloudapi/v2/openapi.v2.gen.go @@ -331,10 +331,32 @@ type Customizations struct { // on the image CustomRepositories *[]CustomRepository `json:"custom_repositories,omitempty"` Directories *[]Directory `json:"directories,omitempty"` - Files *[]File `json:"files,omitempty"` - Filesystem *[]Filesystem `json:"filesystem,omitempty"` - Openscap *OpenSCAP `json:"openscap,omitempty"` - Packages *[]string `json:"packages,omitempty"` + + // FIDO device onboard configuration + Fdo *FDO `json:"fdo,omitempty"` + Files *[]File `json:"files,omitempty"` + Filesystem *[]Filesystem `json:"filesystem,omitempty"` + + // Firewalld configuration + Firewall *FirewallCustomization `json:"firewall,omitempty"` + + // List of groups to create + Group *[]Group `json:"group,omitempty"` + + // Configures the hostname + Hostname *string `json:"hostname,omitempty"` + + // Ignition configuration + Ignition *Ignition `json:"ignition,omitempty"` + + // Name of the installation device, currently only useful for the edge-simplified-installer type + InstallationDevice *string `json:"installation_device,omitempty"` + Kernel *Kernel `json:"kernel,omitempty"` + + // Locale configuration + Locale *Locale `json:"locale,omitempty"` + Openscap *OpenSCAP `json:"openscap,omitempty"` + Packages *[]string `json:"packages,omitempty"` // Extra repositories for packages specified in customizations. These // repositories will only be used to depsolve and retrieve packages @@ -349,8 +371,14 @@ type Customizations struct { // List of services to enable by default Enabled *[]string `json:"enabled,omitempty"` } `json:"services,omitempty"` + + // List of ssh keys + Sshkey *[]SSHKey `json:"sshkey,omitempty"` Subscription *Subscription `json:"subscription,omitempty"` - Users *[]User `json:"users,omitempty"` + + // Timezone configuration + Timezone *Timezone `json:"timezone,omitempty"` + Users *[]User `json:"users,omitempty"` } // A custom directory to create in the final artifact. @@ -390,6 +418,14 @@ type ErrorList struct { Items []Error `json:"items"` } +// FIDO device onboard configuration +type FDO struct { + DiunPubKeyHash *string `json:"diun_pub_key_hash,omitempty"` + DiunPubKeyInsecure *string `json:"diun_pub_key_insecure,omitempty"` + DiunPubKeyRootCerts *string `json:"diun_pub_key_root_certs,omitempty"` + ManufacturingServerUrl *string `json:"manufacturing_server_url,omitempty"` +} + // A custom file to create in the final artifact. type File struct { // Contents of the file as plain text @@ -418,6 +454,21 @@ type Filesystem struct { Mountpoint string `json:"mountpoint"` } +// Firewalld configuration +type FirewallCustomization struct { + // List of ports (or port ranges) and protocols to open + Ports *[]string `json:"ports,omitempty"` + + // Firewalld services to enable or disable + Services *struct { + // List of services to disable + Disabled *[]string `json:"disabled,omitempty"` + + // List of services to enable + Enabled *[]string `json:"enabled,omitempty"` + } `json:"services,omitempty"` +} + // GCPUploadOptions defines model for GCPUploadOptions. type GCPUploadOptions struct { // Name of an existing STANDARD Storage class Bucket. @@ -456,6 +507,32 @@ type GCPUploadStatus struct { ProjectId string `json:"project_id"` } +// Group defines model for Group. +type Group struct { + // Group id of the group to create (optional) + Gid *int `json:"gid,omitempty"` + + // Name of the group to create + Name string `json:"name"` +} + +// Ignition configuration +type Ignition struct { + Embedded *IgnitionEmbedded `json:"embedded,omitempty"` + Firstboot *IgnitionFirstboot `json:"firstboot,omitempty"` +} + +// IgnitionEmbedded defines model for IgnitionEmbedded. +type IgnitionEmbedded struct { + Config string `json:"config"` +} + +// IgnitionFirstboot defines model for IgnitionFirstboot. +type IgnitionFirstboot struct { + // Provisioning URL + Url string `json:"url"` +} + // ImageRequest defines model for ImageRequest. type ImageRequest struct { Architecture string `json:"architecture"` @@ -488,6 +565,15 @@ type ImageStatusValue string // ImageTypes defines model for ImageTypes. type ImageTypes string +// Kernel defines model for Kernel. +type Kernel struct { + // Appends arguments to the bootloader kernel command line + Append *string `json:"append,omitempty"` + + // Name of the kernel to use + Name *string `json:"name,omitempty"` +} + // Koji defines model for Koji. type Koji struct { Name string `json:"name"` @@ -524,6 +610,15 @@ type LocalUploadOptions struct { LocalSave bool `json:"local_save"` } +// Locale configuration +type Locale struct { + // Sets the keyboard layout + Keyboard *string `json:"keyboard,omitempty"` + + // List of locales to be installed, the first one becomes primary, subsequent ones are secondary + Languages *[]string `json:"languages,omitempty"` +} + // OCIUploadOptions defines model for OCIUploadOptions. type OCIUploadOptions map[string]interface{} @@ -605,6 +700,15 @@ type Repository struct { Rhsm *bool `json:"rhsm,omitempty"` } +// SSHKey defines model for SSHKey. +type SSHKey struct { + // Adds the key to the user's authorized_keys file + Key string `json:"key"` + + // User to configure the ssh key for + User string `json:"user"` +} + // Subscription defines model for Subscription. type Subscription struct { ActivationKey string `json:"activation_key"` @@ -617,6 +721,15 @@ type Subscription struct { ServerUrl string `json:"server_url"` } +// Timezone configuration +type Timezone struct { + // List of ntp servers + Ntpservers *[]string `json:"ntpservers,omitempty"` + + // Name of the timezone, defaults to UTC + Timezone *string `json:"timezone,omitempty"` +} + // This should really be oneOf but AWSS3UploadOptions is a subset of // AWSEC2UploadOptions. This means that all AWSEC2UploadOptions objects // are also valid AWSS3UploadOptionas objects which violates the oneOf @@ -923,138 +1036,152 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "DIEAAA==", + "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", + "hwm+iBdcvxsNsw7O1+//PwAA///a3fCCYpAAAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/cloudapi/v2/openapi.v2.yml b/internal/cloudapi/v2/openapi.v2.yml index 0130d15f6..b1a5626e9 100644 --- a/internal/cloudapi/v2/openapi.v2.yml +++ b/internal/cloudapi/v2/openapi.v2.yml @@ -1156,6 +1156,37 @@ components: items: type: string example: "firewalld" + hostname: + type: string + description: Configures the hostname + example: myhostname + kernel: + $ref: '#/components/schemas/Kernel' + sshkey: + type: array + description: List of ssh keys + items: + $ref: '#/components/schemas/SSHKey' + group: + type: array + description: List of groups to create + items: + $ref: '#/components/schemas/Group' + timezone: + $ref: '#/components/schemas/Timezone' + locale: + $ref: '#/components/schemas/Locale' + firewall: + $ref: '#/components/schemas/FirewallCustomization' + installation_device: + type: string + description: | + Name of the installation device, currently only useful for the edge-simplified-installer type + example: /dev/sda + fdo: + $ref: '#/components/schemas/FDO' + ignition: + $ref: '#/components/schemas/Ignition' Container: type: object required: @@ -1172,6 +1203,34 @@ components: type: boolean description: Control TLS verifification example: true + FirewallCustomization: + type: object + description: Firewalld configuration + additionalProperties: false + properties: + ports: + type: array + description: List of ports (or port ranges) and protocols to open + example: ["22:tcp", "80:tcp", "imap:tcp"] + items: + type: string + services: + type: object + description: Firewalld services to enable or disable + additionalProperties: false + properties: + enabled: + type: array + description: List of services to enable + example: ["ftp", "ntp"] + items: + type: string + disabled: + type: array + description: List of services to disable + example: ["telnet"] + items: + type: string Directory: type: object description: | @@ -1328,6 +1387,116 @@ components: key: type: string example: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINrGKErMYi+MMUwuHaRAJmRLoIzRf2qD2dD5z0BTx/6x" + Kernel: + type: object + additionalProperties: false + properties: + name: + type: string + description: Name of the kernel to use + example: kernel-debug + append: + type: string + description: Appends arguments to the bootloader kernel command line + example: nosmt=force + SSHKey: + type: object + additionalProperties: false + required: + - user + - key + properties: + user: + type: string + description: User to configure the ssh key for + example: admin + key: + type: string + description: Adds the key to the user's authorized_keys file + example: | + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIASWitkOH4U874EdsBUnytb3bwvRggHlQlbYXl7n10v9 + Timezone: + type: object + description: Timezone configuration + additionalProperties: false + properties: + timezone: + type: string + description: Name of the timezone, defaults to UTC + example: US/Eastern + ntpservers: + type: array + description: List of ntp servers + example: ["0.north-america.pool.ntp.org", "1.north-america.pool.ntp.org"] + items: + type: string + Locale: + type: object + description: Locale configuration + additionalProperties: false + properties: + languages: + type: array + description: | + List of locales to be installed, the first one becomes primary, subsequent ones are secondary + example: ["en_US.UTF-8"] + items: + type: string + keyboard: + type: string + description: Sets the keyboard layout + example: us + FDO: + type: object + additionalProperties: false + description: FIDO device onboard configuration + properties: + manufacturing_server_url: + type: string + diun_pub_key_insecure: + type: string + diun_pub_key_hash: + type: string + diun_pub_key_root_certs: + type: string + Ignition: + type: object + additionalProperties: false + description: Ignition configuration + properties: + embedded: + $ref: '#/components/schemas/IgnitionEmbedded' + firstboot: + $ref: '#/components/schemas/IgnitionFirstboot' + IgnitionEmbedded: + type: object + additionalProperties: false + required: + - config + properties: + config: + type: string + IgnitionFirstboot: + type: object + additionalProperties: false + required: + - url + properties: + url: + type: string + description: Provisioning URL + Group: + type: object + additionalProperties: false + required: + - name + properties: + name: + type: string + description: Name of the group to create + gid: + type: integer + description: Group id of the group to create (optional) Koji: type: object additionalProperties: false diff --git a/test/cases/api.sh b/test/cases/api.sh index fa2f4c09e..805e3048e 100755 --- a/test/cases/api.sh +++ b/test/cases/api.sh @@ -414,6 +414,26 @@ EOF esac export OPENSCAP_CUSTOMIZATION_BLOCK +TIMEZONE_CUSTOMIZATION_BLOCK=$(cat <