From 54a560670e53e569cc0d2c0171674c8189385c98 Mon Sep 17 00:00:00 2001 From: Sanne Raymaekers Date: Thu, 11 Jan 2024 14:25:44 +0100 Subject: [PATCH] api: update image builder api Include the experimental blueprint endpoints. --- api/config/imageBuilder.ts | 5 + api/schema/imageBuilder.yaml | 882 +++++++++++++++++++++++++++-------- src/store/imageBuilderApi.ts | 257 +++++++++- 3 files changed, 952 insertions(+), 192 deletions(-) diff --git a/api/config/imageBuilder.ts b/api/config/imageBuilder.ts index eb4e694f..55857a51 100644 --- a/api/config/imageBuilder.ts +++ b/api/config/imageBuilder.ts @@ -18,6 +18,11 @@ const config: ConfigFile = { 'getPackages', 'getOscapProfiles', 'getOscapCustomizations', + 'createBlueprint', + 'updateBlueprint', + 'composeBlueprint', + 'getBlueprints', + 'getBlueprintComposes', ], }; diff --git a/api/schema/imageBuilder.yaml b/api/schema/imageBuilder.yaml index bf8e1f3f..d3b8c791 100644 --- a/api/schema/imageBuilder.yaml +++ b/api/schema/imageBuilder.yaml @@ -259,7 +259,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/UploadStatus' + $ref: '#/components/schemas/CloneStatusResponse' /compose: post: summary: compose image @@ -414,6 +414,161 @@ paths: application/json: schema: $ref: '#/components/schemas/HTTPErrorList' + /experimental/blueprint/{id}: + put: + parameters: + - in: path + name: id + schema: + type: string + format: uuid + example: '123e4567-e89b-12d3-a456-426655440000' + required: true + description: UUID of a blueprint + summary: update blueprint + description: "update blueprint" + operationId: updateBlueprint + requestBody: + required: true + description: details of blueprint + content: + application/json: + schema: + $ref: "#/components/schemas/CreateBlueprintRequest" + responses: + '200': + description: blueprint was update + content: + application/json: + schema: + $ref: '#/components/schemas/CreateBlueprintResponse' + '404': + description: blueprint was not found + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPErrorList' + /experimental/blueprint/{id}/compose: + post: + parameters: + - in: path + name: id + schema: + type: string + format: uuid + example: '123e4567-e89b-12d3-a456-426655440000' + required: true + description: UUID of a blueprint + summary: create new compose from blueprint + description: "create new compose from blueprint" + operationId: composeBlueprint + responses: + '201': + description: compose was created + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ComposeResponse' + '403': + description: user is not allowed to compose from blueprints + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPErrorList' + /experimental/blueprints: + get: + summary: get a collection of blueprints + description: "get a collection of blueprints, returns just the latest version of each blueprint" + operationId: getBlueprints + parameters: + - in: query + name: search + required: false + schema: + type: string + description: search for blueprints by name or description + - in: query + name: limit + schema: + type: integer + default: 100 + minimum: 1 + maximum: 100 + description: max amount of blueprints, default 100 + - in: query + name: offset + schema: + type: integer + default: 0 + minimum: 0 + description: blueprint page offset, default 0 + responses: + '200': + description: a list of blueprints + content: + application/json: + schema: + $ref: '#/components/schemas/BlueprintsResponse' + /experimental/blueprint/{id}/composes: + get: + summary: get composes associated with a blueprint + description: "get a collection of composes associated to a blueprint, allows for filtering by version" + operationId: getBlueprintComposes + parameters: + - in: path + name: id + schema: + type: string + format: uuid + example: '123e4567-e89b-12d3-a456-426655440000' + required: true + description: UUID of a blueprint + - in: query + name: blueprint_version + schema: + type: integer + description: | + Filter by a specific version of the Blueprint we want to fetch composes for + - in: query + name: limit + schema: + type: integer + default: 100 + minimum: 1 + maximum: 100 + description: max amount of composes, default 100 + - in: query + name: offset + schema: + type: integer + default: 0 + minimum: 0 + description: composes page offset, default 0 + - in: query + name: ignoreImageTypes + required: false + schema: + type: array + items: + $ref: '#/components/schemas/ImageTypes' + example: ['rhel-edge-installer', 'rhel-edge-commit', ...] + description: | + Filter the composes on image type. The filter is optional and can be specified multiple times. + responses: + '200': + description: a list of composes + content: + application/json: + schema: + $ref: '#/components/schemas/ComposesResponse' + '404': + description: blueprint was not found + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPErrorList' components: schemas: @@ -520,6 +675,16 @@ components: reason: type: string details: {} + CloneStatusResponse: + required: + - compose_id + allOf: + - type: object + properties: + compose_id: + type: string + format: uuid + - $ref: '#/components/schemas/UploadStatus' UploadStatus: required: - status @@ -651,6 +816,52 @@ components: id: type: string format: uuid + BlueprintsResponse: + required: + - meta + - links + - data + properties: + meta: + type: object + required: + - count + properties: + count: + type: integer + links: + type: object + required: + - first + - last + properties: + first: + type: string + last: + type: string + data: + type: array + items: + $ref: '#/components/schemas/BlueprintItem' + BlueprintItem: + required: + - id + - version + - name + - description + - last_modified_at + properties: + id: + type: string + format: uuid + version: + type: integer + name: + type: string + description: + type: string + last_modified_at: + type: string Distributions: type: string description: | @@ -771,6 +982,13 @@ components: type: string client_id: $ref: '#/components/schemas/ClientId' + blueprint_id: + type: string + format: uuid + nullable: true + blueprint_version: + type: integer + nullable: true ClientId: type: string enum: ["api", "ui"] @@ -891,105 +1109,6 @@ components: The total length is limited to 60 characters. OCIUploadRequestOptions: type: object - Customizations: - type: object - properties: - subscription: - $ref: '#/components/schemas/Subscription' - packages: - type: array - maxItems: 10000 - example: ['postgresql'] - items: - type: string - payload_repositories: - type: array - items: - $ref: '#/components/schemas/Repository' - custom_repositories: - type: array - items: - $ref: '#/components/schemas/CustomRepository' - openscap: - $ref: '#/components/schemas/OpenSCAP' - filesystem: - type: array - maxItems: 128 - items: - $ref: '#/components/schemas/Filesystem' - users: - type: array - items: - $ref: '#/components/schemas/User' - description: - "list of users that a customer can add, also specifying their respective groups and SSH keys" - partitioning_mode: - type: string - enum: - - raw - - lvm - - auto-lvm - description: | - Select how the disk image will be partitioned. 'auto-lvm' will use raw unless - there are one or more mountpoints in which case it will use LVM. 'lvm' always - uses LVM, even when there are no extra mountpoints. 'raw' uses raw partitions - even when there are one or more mountpoints. - User: - type: object - required: - - name - - ssh_key - properties: - name: - type: string - example: "user1" - ssh_key: - type: string - example: "ssh-rsa AAAAB3NzaC1" - Filesystem: - type: object - required: - - mountpoint - - min_size - properties: - mountpoint: - type: string - example: '/var' - min_size: - x-go-type: uint64 - example: 2147483648 - description: 'size of the filesystem in bytes' - Subscription: - type: object - required: - - organization - - activation-key - - server-url - - base-url - - insights - properties: - organization: - type: integer - example: 2040324 - activation-key: - type: string - format: password - example: 'my-secret-key' - server-url: - type: string - example: 'subscription.rhsm.redhat.com' - base-url: - type: string - example: http://cdn.redhat.com/ - insights: - type: boolean - example: true - rhc: - type: boolean - default: false - example: true - description: | - Optional flag to use rhc to register the system, which also always enables Insights. OSTree: type: object properties: @@ -1091,97 +1210,6 @@ components: type: string signature: type: string - Repository: - type: object - required: - - rhsm - properties: - rhsm: - type: boolean - baseurl: - type: string - format: uri - example: 'https://cdn.redhat.com/content/dist/rhel8/8/x86_64/baseos/os/' - mirrorlist: - type: string - format: uri - example: 'http://mirrorlist.centos.org/?release=8-stream&arch=aarch64&repo=BaseOS' - metalink: - type: string - format: uri - example: 'https://mirrors.fedoraproject.org/metalink?repo=fedora-32&arch=x86_64' - gpgkey: - type: string - check_gpg: - type: boolean - check_repo_gpg: - type: boolean - default: false - description: | - Enables gpg verification of the repository metadata - ignore_ssl: - type: boolean - CustomRepository: - type: object - required: - - id - description: | - Repository configuration for custom repositories. - At least one of the 'baseurl', 'mirrorlist', 'metalink' properties must - be specified. If more of them are specified, the order of precedence is - the same as listed above. Id is required. - properties: - id: - type: string - name: - type: string - filename: - type: string - baseurl: - type: array - example: [ 'https://cdn.redhat.com/content/dist/rhel8/8/x86_64/baseos/os/' ] - items: - type: string - format: uri - mirrorlist: - type: string - format: uri - example: 'http://mirrorlist.centos.org/?release=8-stream&arch=aarch64&repo=BaseOS' - metalink: - type: string - format: uri - example: 'https://mirrors.fedoraproject.org/metalink?repo=fedora-32&arch=x86_64' - gpgkey: - type: array - example: [ "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGAcScoBEADLf8YHkezJ6adlMYw7aGGIlJalt8Jj2x/B2K+hIfIuxGtpVj7e\nLRgDU76jaT5pVD5mFMJ3pkeneR/cTmqqQkNyQshX2oQXwEzUSb1CNMCfCGgkX8Q2\nzZkrIcCrF0Q2wrKblaudhU+iVanADsm18YEqsb5AU37dtUrM3QYdWg9R+XiPfV8R\nKBjT03vVBOdMSsY39LaCn6Ip1Ovp8IEo/IeEVY1qmCOPAaK0bJH3ufg4Cueks+TS\nwQWTeCLxuZL6OMXoOPKwvMQfxbg1XD8vuZ0Ktj/cNH2xau0xmsAu9HJpekvOPRxl\nyqtjyZfroVieFypwZgvQwtnnM8/gSEu/JVTrY052mEUT7Ccb74kcHFTFfMklnkG/\n0fU4ARa504H3xj0ktbe3vKcPXoPOuKBVsHSv00UGYAyPeuy+87cU/YEhM7k3SVKj\n6eIZgyiMO0wl1YGDRKculwks9A+ulkg1oTb4s3zmZvP07GoTxW42jaK5WS+NhZee\n860XoVhbc1KpS+jfZojsrEtZ8PbUZ+YvF8RprdWArjHbJk2JpRKAxThxsQAsBhG1\n0Lux2WaMB0g2I5PcMdJ/cqjo08ccrjBXuixWri5iu9MXp8qT/fSzNmsdIgn8/qZK\ni8Qulfu77uqhW/wt2btnitgRsqjhxMujYU4Zb4hktF8hKU/XX742qhL5KwARAQAB\ntDFGZWRvcmEgKDM1KSA8ZmVkb3JhLTM1LXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQJOBBMBCAA4FiEEeH6mrhFH7uVsQLMM20Y5cZhnxY8FAmAcScoCGw8FCwkI\nBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ20Y5cZhnxY+NYA/7BYpglySAZYHhjyKh\n/+f6zPfVvbH20Eq3kI7OFBN0nLX+BU1muvS+qTuS3WLrB3m3GultpKREJKLtm5ED\n1rGzXAoT1yp9YI8LADdMCCOyjAjsoWU87YUuC+/bnjrTeR2LROCfyPC76W985iOV\nm5S+bsQDw7C2LrldAM4MDuoyZ1SitGaZ4KQLVt+TEa14isYSGCjzo7PY8V3JOk50\ngqWg82N/bm2EzS7T83WEDb1lvj4IlvxgIqKeg11zXYxmrYSZJJCfvzf+lNS6uxgH\njx/J0ylZ2LibGr6GAAyO9UWrAZSwSM0EcjT8wECnxkSDuyqmWwVvNBXuEIV8Oe3Y\nMiU1fJN8sd7DpsFx5M+XdnMnQS+HrjTPKD3mWrlAdnEThdYV8jZkpWhDys3/99eO\nhk0rLny0jNwkauf/iU8Oc6XvMkjLRMJg5U9VKyJuWWtzwXnjMN5WRFBqK4sZomMM\nftbTH1+5ybRW/A3vBbaxRW2t7UzNjczekSZEiaLN9L/HcJCIR1QF8682DdAlEF9d\nk2gQiYSQAaaJ0JJAzHvRkRJLLgK2YQYiHNVy2t3JyFfsram5wSCWOfhPeIyLBTZJ\nvrpNlPbefsT957Tf2BNIugzZrC5VxDSKkZgRh1VGvSIQnCyzkQy6EU2qPpiW59G/\nhPIXZrKocK3KLS9/izJQTRltjMA=\n=PfT7\n-----END PGP PUBLIC KEY BLOCK-----\n" ] - description: 'GPG key used to sign packages in this repository. Can be a gpg key or a URL' - items: - type: string - check_gpg: - type: boolean - check_repo_gpg: - type: boolean - enabled: - type: boolean - priority: - type: integer - ssl_verify: - type: boolean - OpenSCAP: - type: object - required: - - profile_id - properties: - profile_id: - type: string - example: "xccdf_org.ssgproject.content_profile_cis" - description: "The policy reference ID" - profile_name: - type: string - description: "The policy type" - profile_description: - type: string - description: "The longform policy description" ClonesResponse: required: - meta @@ -1292,3 +1320,475 @@ components: - xccdf_org.ssgproject.content_profile_standard - xccdf_org.ssgproject.content_profile_stig - xccdf_org.ssgproject.content_profile_stig_gui + + # all customizations and sub-objects + Customizations: + type: object + properties: + containers: + type: array + items: + $ref: '#/components/schemas/Container' + description: Container images to embed into the final artfact + directories: + type: array + items: + $ref: '#/components/schemas/Directory' + description: Directories to create in the final artifact + files: + type: array + items: + $ref: '#/components/schemas/File' + description: Files to create in the final artifact + subscription: + $ref: '#/components/schemas/Subscription' + packages: + type: array + maxItems: 10000 + example: ['postgresql'] + items: + type: string + payload_repositories: + type: array + items: + $ref: '#/components/schemas/Repository' + custom_repositories: + type: array + items: + $ref: '#/components/schemas/CustomRepository' + openscap: + $ref: '#/components/schemas/OpenSCAP' + filesystem: + type: array + maxItems: 128 + items: + $ref: '#/components/schemas/Filesystem' + users: + type: array + items: + $ref: '#/components/schemas/User' + description: + "list of users that a customer can add, also specifying their respective groups and SSH keys" + services: + $ref: '#/components/schemas/Services' + hostname: + type: string + description: Configures the hostname + example: myhostname + kernel: + $ref: '#/components/schemas/Kernel' + groups: + 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' + partitioning_mode: + type: string + enum: + - raw + - lvm + - auto-lvm + description: | + Select how the disk image will be partitioned. 'auto-lvm' will use raw unless + there are one or more mountpoints in which case it will use LVM. 'lvm' always + uses LVM, even when there are no extra mountpoints. 'raw' uses raw partitions + even when there are one or more mountpoints. + fips: + $ref: '#/components/schemas/FIPS' + Container: + type: object + required: + - source + properties: + source: + type: string + description: Reference to the container to embed + example: 'registry.example.com/image:tag' + name: + type: string + description: Name to use for the container from the image + tls_verify: + 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: | + A custom directory to create in the final artifact. + required: + - path + properties: + path: + type: string + description: Path to the directory + example: '/etc/mydir' + mode: + type: string + description: Permissions string for the directory in octal format + example: "0755" + user: + oneOf: + - type: string + - type: integer + description: Owner of the directory as a user name or a uid + example: 'root' + group: + oneOf: + - type: string + - type: integer + description: Group of the directory as a group name or a gid + example: 'root' + ensure_parents: + type: boolean + description: Ensure that the parent directories exist + default: false + File: + type: object + description: | + A custom file to create in the final artifact. + required: + - path + properties: + path: + type: string + description: Path to the file + example: '/etc/myfile' + mode: + type: string + description: Permissions string for the file in octal format + example: "0644" + user: + oneOf: + - type: string + - type: integer + description: Owner of the file as a uid or a user name + example: 'root' + group: + oneOf: + - type: string + - type: integer + description: Group of the file as a gid or a group name + example: 'root' + data: + type: string + description: Contents of the file as plain text + ensure_parents: + type: boolean + description: Ensure that the parent directories exist + example: true + default: false + 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 + Services: + type: object + additionalProperties: false + properties: + enabled: + description: List of services to enable by default + type: array + minItems: 1 + items: + type: string + example: "nftables" + disabled: + description: List of services to disable by default + type: array + minItems: 1 + items: + type: string + example: "firewalld" + 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 + FIPS: + type: object + additionalProperties: false + description: System FIPS mode setup + properties: + enabled: + type: boolean + description: Enables the system FIPS mode + default: false + 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) + User: + type: object + required: + - name + - ssh_key + properties: + name: + type: string + example: "user1" + ssh_key: + type: string + example: "ssh-rsa AAAAB3NzaC1" + Filesystem: + type: object + required: + - mountpoint + - min_size + properties: + mountpoint: + type: string + example: '/var' + min_size: + x-go-type: uint64 + example: 2147483648 + description: 'size of the filesystem in bytes' + Subscription: + type: object + required: + - organization + - activation-key + - server-url + - base-url + - insights + properties: + organization: + type: integer + example: 2040324 + activation-key: + type: string + format: password + example: 'my-secret-key' + server-url: + type: string + example: 'subscription.rhsm.redhat.com' + base-url: + type: string + example: http://cdn.redhat.com/ + insights: + type: boolean + example: true + rhc: + type: boolean + default: false + example: true + description: | + Optional flag to use rhc to register the system, which also always enables Insights. + OpenSCAP: + type: object + required: + - profile_id + properties: + profile_id: + type: string + example: "xccdf_org.ssgproject.content_profile_cis" + description: "The policy reference ID" + profile_name: + type: string + description: "The policy type" + profile_description: + type: string + description: "The longform policy description" + CustomRepository: + type: object + required: + - id + description: | + Repository configuration for custom repositories. + At least one of the 'baseurl', 'mirrorlist', 'metalink' properties must + be specified. If more of them are specified, the order of precedence is + the same as listed above. Id is required. + properties: + id: + type: string + name: + type: string + filename: + type: string + baseurl: + type: array + example: [ 'https://cdn.redhat.com/content/dist/rhel8/8/x86_64/baseos/os/' ] + items: + type: string + format: uri + mirrorlist: + type: string + format: uri + example: 'http://mirrorlist.centos.org/?release=8-stream&arch=aarch64&repo=BaseOS' + metalink: + type: string + format: uri + example: 'https://mirrors.fedoraproject.org/metalink?repo=fedora-32&arch=x86_64' + gpgkey: + type: array + example: [ "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGAcScoBEADLf8YHkezJ6adlMYw7aGGIlJalt8Jj2x/B2K+hIfIuxGtpVj7e\nLRgDU76jaT5pVD5mFMJ3pkeneR/cTmqqQkNyQshX2oQXwEzUSb1CNMCfCGgkX8Q2\nzZkrIcCrF0Q2wrKblaudhU+iVanADsm18YEqsb5AU37dtUrM3QYdWg9R+XiPfV8R\nKBjT03vVBOdMSsY39LaCn6Ip1Ovp8IEo/IeEVY1qmCOPAaK0bJH3ufg4Cueks+TS\nwQWTeCLxuZL6OMXoOPKwvMQfxbg1XD8vuZ0Ktj/cNH2xau0xmsAu9HJpekvOPRxl\nyqtjyZfroVieFypwZgvQwtnnM8/gSEu/JVTrY052mEUT7Ccb74kcHFTFfMklnkG/\n0fU4ARa504H3xj0ktbe3vKcPXoPOuKBVsHSv00UGYAyPeuy+87cU/YEhM7k3SVKj\n6eIZgyiMO0wl1YGDRKculwks9A+ulkg1oTb4s3zmZvP07GoTxW42jaK5WS+NhZee\n860XoVhbc1KpS+jfZojsrEtZ8PbUZ+YvF8RprdWArjHbJk2JpRKAxThxsQAsBhG1\n0Lux2WaMB0g2I5PcMdJ/cqjo08ccrjBXuixWri5iu9MXp8qT/fSzNmsdIgn8/qZK\ni8Qulfu77uqhW/wt2btnitgRsqjhxMujYU4Zb4hktF8hKU/XX742qhL5KwARAQAB\ntDFGZWRvcmEgKDM1KSA8ZmVkb3JhLTM1LXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQJOBBMBCAA4FiEEeH6mrhFH7uVsQLMM20Y5cZhnxY8FAmAcScoCGw8FCwkI\nBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ20Y5cZhnxY+NYA/7BYpglySAZYHhjyKh\n/+f6zPfVvbH20Eq3kI7OFBN0nLX+BU1muvS+qTuS3WLrB3m3GultpKREJKLtm5ED\n1rGzXAoT1yp9YI8LADdMCCOyjAjsoWU87YUuC+/bnjrTeR2LROCfyPC76W985iOV\nm5S+bsQDw7C2LrldAM4MDuoyZ1SitGaZ4KQLVt+TEa14isYSGCjzo7PY8V3JOk50\ngqWg82N/bm2EzS7T83WEDb1lvj4IlvxgIqKeg11zXYxmrYSZJJCfvzf+lNS6uxgH\njx/J0ylZ2LibGr6GAAyO9UWrAZSwSM0EcjT8wECnxkSDuyqmWwVvNBXuEIV8Oe3Y\nMiU1fJN8sd7DpsFx5M+XdnMnQS+HrjTPKD3mWrlAdnEThdYV8jZkpWhDys3/99eO\nhk0rLny0jNwkauf/iU8Oc6XvMkjLRMJg5U9VKyJuWWtzwXnjMN5WRFBqK4sZomMM\nftbTH1+5ybRW/A3vBbaxRW2t7UzNjczekSZEiaLN9L/HcJCIR1QF8682DdAlEF9d\nk2gQiYSQAaaJ0JJAzHvRkRJLLgK2YQYiHNVy2t3JyFfsram5wSCWOfhPeIyLBTZJ\nvrpNlPbefsT957Tf2BNIugzZrC5VxDSKkZgRh1VGvSIQnCyzkQy6EU2qPpiW59G/\nhPIXZrKocK3KLS9/izJQTRltjMA=\n=PfT7\n-----END PGP PUBLIC KEY BLOCK-----\n" ] + description: 'GPG key used to sign packages in this repository. Can be a gpg key or a URL' + items: + type: string + check_gpg: + type: boolean + check_repo_gpg: + type: boolean + enabled: + type: boolean + priority: + type: integer + ssl_verify: + type: boolean + module_hotfixes: + type: boolean + Repository: + type: object + required: + - rhsm + properties: + rhsm: + type: boolean + baseurl: + type: string + format: uri + example: 'https://cdn.redhat.com/content/dist/rhel8/8/x86_64/baseos/os/' + mirrorlist: + type: string + format: uri + example: 'http://mirrorlist.centos.org/?release=8-stream&arch=aarch64&repo=BaseOS' + metalink: + type: string + format: uri + example: 'https://mirrors.fedoraproject.org/metalink?repo=fedora-32&arch=x86_64' + gpgkey: + type: string + check_gpg: + type: boolean + check_repo_gpg: + type: boolean + default: false + description: | + Enables gpg verification of the repository metadata + ignore_ssl: + type: boolean + module_hotfixes: + type: boolean diff --git a/src/store/imageBuilderApi.ts b/src/store/imageBuilderApi.ts index 5307fd29..6c8f2ae7 100644 --- a/src/store/imageBuilderApi.ts +++ b/src/store/imageBuilderApi.ts @@ -80,6 +80,59 @@ const injectedRtkApi = api.injectEndpoints({ url: `/oscap/${queryArg.distribution}/${queryArg.profile}/customizations`, }), }), + createBlueprint: build.mutation< + CreateBlueprintApiResponse, + CreateBlueprintApiArg + >({ + query: (queryArg) => ({ + url: `/experimental/blueprint`, + method: "POST", + body: queryArg.createBlueprintRequest, + }), + }), + updateBlueprint: build.mutation< + UpdateBlueprintApiResponse, + UpdateBlueprintApiArg + >({ + query: (queryArg) => ({ + url: `/experimental/blueprint/${queryArg.id}`, + method: "PUT", + body: queryArg.createBlueprintRequest, + }), + }), + composeBlueprint: build.mutation< + ComposeBlueprintApiResponse, + ComposeBlueprintApiArg + >({ + query: (queryArg) => ({ + url: `/experimental/blueprint/${queryArg.id}/compose`, + method: "POST", + }), + }), + getBlueprints: build.query({ + query: (queryArg) => ({ + url: `/experimental/blueprints`, + params: { + search: queryArg.search, + limit: queryArg.limit, + offset: queryArg.offset, + }, + }), + }), + getBlueprintComposes: build.query< + GetBlueprintComposesApiResponse, + GetBlueprintComposesApiArg + >({ + query: (queryArg) => ({ + url: `/experimental/blueprint/${queryArg.id}/composes`, + params: { + blueprint_version: queryArg.blueprintVersion, + limit: queryArg.limit, + offset: queryArg.offset, + ignoreImageTypes: queryArg.ignoreImageTypes, + }, + }), + }), }), overrideExisting: false, }); @@ -126,7 +179,7 @@ export type GetComposeClonesApiArg = { offset?: number; }; export type GetCloneStatusApiResponse = - /** status 200 clone status */ UploadStatus; + /** status 200 clone status */ CloneStatusResponse; export type GetCloneStatusApiArg = { /** Id of clone status to get */ id: string; @@ -165,6 +218,52 @@ export type GetOscapCustomizationsApiArg = { /** Name of the profile to retrieve customizations from */ profile: DistributionProfileItem; }; +export type CreateBlueprintApiResponse = + /** status 201 blueprint was saved */ CreateBlueprintResponse; +export type CreateBlueprintApiArg = { + /** details of blueprint */ + createBlueprintRequest: CreateBlueprintRequest; +}; +export type UpdateBlueprintApiResponse = + /** status 200 blueprint was update */ CreateBlueprintResponse; +export type UpdateBlueprintApiArg = { + /** UUID of a blueprint */ + id: string; + /** details of blueprint */ + createBlueprintRequest: CreateBlueprintRequest; +}; +export type ComposeBlueprintApiResponse = + /** status 201 compose was created */ ComposeResponse[]; +export type ComposeBlueprintApiArg = { + /** UUID of a blueprint */ + id: string; +}; +export type GetBlueprintsApiResponse = + /** status 200 a list of blueprints */ BlueprintsResponse; +export type GetBlueprintsApiArg = { + /** search for blueprints by name or description */ + search?: string; + /** max amount of blueprints, default 100 */ + limit?: number; + /** blueprint page offset, default 0 */ + offset?: number; +}; +export type GetBlueprintComposesApiResponse = + /** status 200 a list of composes */ ComposesResponse; +export type GetBlueprintComposesApiArg = { + /** UUID of a blueprint */ + id: string; + /** Filter by a specific version of the Blueprint we want to fetch composes for + */ + blueprintVersion?: number; + /** max amount of composes, default 100 */ + limit?: number; + /** composes page offset, default 0 */ + offset?: number; + /** Filter the composes on image type. The filter is optional and can be specified multiple times. + */ + ignoreImageTypes?: ImageTypes[]; +}; export type Repository = { rhsm: boolean; baseurl?: string; @@ -176,6 +275,7 @@ export type Repository = { */ check_repo_gpg?: boolean; ignore_ssl?: boolean; + module_hotfixes?: boolean; }; export type ArchitectureItem = { arch: string; @@ -318,6 +418,40 @@ export type ImageRequest = { */ size?: any; }; +export type Container = { + /** Reference to the container to embed */ + source: string; + /** Name to use for the container from the image */ + name?: string; + /** Control TLS verifification */ + tls_verify?: boolean; +}; +export type Directory = { + /** Path to the directory */ + path: string; + /** Permissions string for the directory in octal format */ + mode?: string; + /** Owner of the directory as a user name or a uid */ + user?: string | number; + /** Group of the directory as a group name or a gid */ + group?: string | number; + /** Ensure that the parent directories exist */ + ensure_parents?: boolean; +}; +export type File = { + /** Path to the file */ + path: string; + /** Permissions string for the file in octal format */ + mode?: string; + /** Owner of the file as a uid or a user name */ + user?: string | number; + /** Group of the file as a gid or a group name */ + group?: string | number; + /** Contents of the file as plain text */ + data?: string; + /** Ensure that the parent directories exist */ + ensure_parents?: boolean; +}; export type Subscription = { organization: number; "activation-key": string; @@ -342,6 +476,7 @@ export type CustomRepository = { enabled?: boolean; priority?: number; ssl_verify?: boolean; + module_hotfixes?: boolean; }; export type OpenScap = { /** The policy reference ID */ @@ -360,7 +495,73 @@ export type User = { name: string; ssh_key: string; }; +export type Services = { + /** List of services to enable by default */ + enabled?: string[]; + /** List of services to disable by default */ + disabled?: string[]; +}; +export type Kernel = { + /** Name of the kernel to use */ + name?: string; + /** Appends arguments to the bootloader kernel command line */ + append?: string; +}; +export type Group = { + /** Name of the group to create */ + name: string; + /** Group id of the group to create (optional) */ + gid?: number; +}; +export type Timezone = { + /** Name of the timezone, defaults to UTC */ + timezone?: string; + /** List of ntp servers */ + ntpservers?: string[]; +}; +export type Locale = { + /** List of locales to be installed, the first one becomes primary, subsequent ones are secondary + */ + languages?: string[]; + /** Sets the keyboard layout */ + keyboard?: string; +}; +export type FirewallCustomization = { + /** List of ports (or port ranges) and protocols to open */ + ports?: string[]; + /** Firewalld services to enable or disable */ + services?: { + /** List of services to enable */ + enabled?: string[]; + /** List of services to disable */ + disabled?: string[]; + }; +}; +export type Fdo = { + manufacturing_server_url?: string; + diun_pub_key_insecure?: string; + diun_pub_key_hash?: string; + diun_pub_key_root_certs?: string; +}; +export type IgnitionEmbedded = { + config: string; +}; +export type IgnitionFirstboot = { + /** Provisioning URL */ + url: string; +}; +export type Ignition = { + embedded?: IgnitionEmbedded; + firstboot?: IgnitionFirstboot; +}; +export type Fips = { + /** Enables the system FIPS mode */ + enabled?: boolean; +}; export type Customizations = { + containers?: Container[]; + directories?: Directory[]; + files?: File[]; subscription?: Subscription; packages?: string[]; payload_repositories?: Repository[]; @@ -369,12 +570,27 @@ export type Customizations = { filesystem?: Filesystem[]; /** list of users that a customer can add, also specifying their respective groups and SSH keys */ users?: User[]; + services?: Services; + /** Configures the hostname */ + hostname?: string; + kernel?: Kernel; + /** List of groups to create */ + groups?: Group[]; + timezone?: Timezone; + locale?: Locale; + firewall?: FirewallCustomization; + /** Name of the installation device, currently only useful for the edge-simplified-installer type + */ + installation_device?: string; + fdo?: Fdo; + ignition?: Ignition; /** Select how the disk image will be partitioned. 'auto-lvm' will use raw unless there are one or more mountpoints in which case it will use LVM. 'lvm' always uses LVM, even when there are no extra mountpoints. 'raw' uses raw partitions even when there are one or more mountpoints. */ partitioning_mode?: "raw" | "lvm" | "auto-lvm"; + fips?: Fips; }; export type ComposeRequest = { distribution: Distributions; @@ -392,6 +608,8 @@ export type ComposesResponseItem = { created_at: string; image_name?: string; client_id?: ClientId; + blueprint_id?: string | null; + blueprint_version?: number | null; }; export type ComposesResponse = { meta: { @@ -482,6 +700,9 @@ export type ClonesResponse = { }; data: ClonesResponseItem[]; }; +export type CloneStatusResponse = { + compose_id?: string; +} & UploadStatus; export type ComposeResponse = { id: string; }; @@ -518,6 +739,35 @@ export type DistributionProfileItem = | "xccdf_org.ssgproject.content_profile_stig" | "xccdf_org.ssgproject.content_profile_stig_gui"; export type DistributionProfileResponse = DistributionProfileItem[]; +export type CreateBlueprintResponse = { + id: string; +}; +export type CreateBlueprintRequest = { + name: string; + description: string; + distribution: Distributions; + /** Array of image requests. Having more image requests in a single blueprint is currently not supported. + */ + image_requests: ImageRequest[]; + customizations: Customizations; +}; +export type BlueprintItem = { + id: string; + version: number; + name: string; + description: string; + last_modified_at: string; +}; +export type BlueprintsResponse = { + meta: { + count: number; + }; + links: { + first: string; + last: string; + }; + data: BlueprintItem[]; +}; export const { useGetArchitecturesQuery, useGetComposesQuery, @@ -529,4 +779,9 @@ export const { useGetPackagesQuery, useGetOscapProfilesQuery, useGetOscapCustomizationsQuery, + useCreateBlueprintMutation, + useUpdateBlueprintMutation, + useComposeBlueprintMutation, + useGetBlueprintsQuery, + useGetBlueprintComposesQuery, } = injectedRtkApi;