extend osbuilder exporter job and osartifact crd spec

This commit is contained in:
Sebastian Florek 2025-01-30 15:02:51 +01:00
parent 3b76681196
commit 2a3c0c9f33
No known key found for this signature in database
GPG Key ID: DBC7C083B0200A0F
12 changed files with 660 additions and 152 deletions

View File

@ -17,6 +17,7 @@ limitations under the License.
package v1alpha2
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -40,45 +41,101 @@ type OSArtifactSpec struct {
// +kubebuilder:validation:Enum:=rpi3;rpi4
Model *Model `json:"model,omitempty"`
CloudConfigRef *SecretKeySelector `json:"cloudConfigRef,omitempty"`
// +optional
CloudConfigRef *corev1.SecretKeySelector `json:"cloudConfigRef,omitempty"`
Bundles []string `json:"bundles,omitempty"`
// +optional
Bundles []string `json:"bundles,omitempty"`
// +optional
FileBundles map[string]string `json:"fileBundles,omitempty"`
OutputImage *OutputImage `json:"outputImage,omitempty"`
}
type SecretKeySelector struct {
Name string `json:"name"`
// Exporter when provided it will spawn an exporter job that
// pushes images built by the osbuilder to the provided registry.
// +optional
Key string `json:"key,omitempty"`
Exporter *ExporterSpec `json:"exporter,omitempty"`
}
type RegistryCloud string
type RegistryType string
const (
// RegistryCloudECR ensures that special env variables will be injected
// RegistryTypeECR ensures that special env variables will be injected
// into the exporter job to allow kaniko to automatically auth with the
// ecr registry to push the images.
RegistryCloudECR RegistryCloud = "ecr"
// RegistryCloudOther requires from user to provide username/password secret
RegistryTypeECR RegistryType = "ecr"
// RegistryTypeOther requires from user to provide username/password secret
// in order for kaniko to be able to authenticate with the container registry.
RegistryCloudOther RegistryCloud = "other"
RegistryTypeOther RegistryType = "other"
)
type OutputImage struct {
type ExporterSpec struct {
// Registry is a registry spec used to push the final images built by the osbuilder.
// +required
Registry RegistrySpec `json:"registry"`
// ServiceAccount allows overriding 'default' SA bound to the exporter pods.
// +optional
ServiceAccount *string `json:"serviceAccount,omitempty"`
// ExtraEnvVars allows to append extra env vars to the exporter pods.
// +optional
ExtraEnvVars *[]corev1.EnvVar `json:"extraEnvVars,omitempty"`
}
func (in *ExporterSpec) IsECRRegistry() bool {
return in.Registry.Type == RegistryTypeECR
}
func (in *ExporterSpec) HasDockerConfigSecret() bool {
return in.Registry.DockerConfigSecretKeyRef != nil
}
func (in *ExporterSpec) HasExtraEnvVars() bool {
return in.ExtraEnvVars != nil && len(*in.ExtraEnvVars) > 0
}
func (in *ExporterSpec) ServiceAccountName() string {
if in.ServiceAccount == nil || len(*in.ServiceAccount) == 0 {
// Default SA name. Always exists.
return "default"
}
return *in.ServiceAccount
}
type ImageSpec struct {
// Repository is the name of repository where image is being pushed.
// +required
Repository string `json:"repository"`
// Tag is the tag name of the image being pushed. Defaults to 'latest' if not provided.
// +optional
Tag string `json:"tag,omitempty"`
}
type RegistrySpec struct {
// Name is a DNS name of the registry. It has to be accessible by the pod.
// +required
Name string `json:"name"`
// Type is a kind of registry being used. Currently supported values are:
// - ecr - Amazon Elastic Container Registry. Use only if a pod runs on
// an eks cluster and has permissions to push to the registry.
// - other - Any other type of the registry. It requires DockerConfigSecretKeyRef
// to be provided in order to auth to the registry.
// +kubebuilder:validation:Enum=ecr;other
// +kubebuilder:default=other
// +required
Cloud RegistryCloud `json:"cloud"`
Type RegistryType `json:"type"`
// Image defines the image details required to push image to the registry.
// +required
Image ImageSpec `json:"image"`
// DockerConfigSecretKeyRef is a reference to the secret that holds the `config.json` auth file.
// It should be in a format that `docker login` can accept to auth to the registry.
// +optional
Registry string `json:"registry,omitempty"`
// +optional
Repository string `json:"repository,omitempty"`
// +optional
Tag string `json:"tag,omitempty"`
// +optional
DockerConfigSecretKeyRef *SecretKeySelector `json:"dockerConfigSecretKeyRef,omitempty"`
DockerConfigSecretKeyRef *corev1.SecretKeySelector `json:"dockerConfigSecretKeyRef,omitempty"`
}
type ArtifactPhase string

View File

@ -21,10 +21,58 @@ limitations under the License.
package v1alpha2
import (
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExporterSpec) DeepCopyInto(out *ExporterSpec) {
*out = *in
in.Registry.DeepCopyInto(&out.Registry)
if in.ServiceAccount != nil {
in, out := &in.ServiceAccount, &out.ServiceAccount
*out = new(string)
**out = **in
}
if in.ExtraEnvVars != nil {
in, out := &in.ExtraEnvVars, &out.ExtraEnvVars
*out = new([]v1.EnvVar)
if **in != nil {
in, out := *in, *out
*out = make([]v1.EnvVar, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExporterSpec.
func (in *ExporterSpec) DeepCopy() *ExporterSpec {
if in == nil {
return nil
}
out := new(ExporterSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageSpec) DeepCopyInto(out *ImageSpec) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageSpec.
func (in *ImageSpec) DeepCopy() *ImageSpec {
if in == nil {
return nil
}
out := new(ImageSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *OSArtifact) DeepCopyInto(out *OSArtifact) {
*out = *in
@ -94,8 +142,8 @@ func (in *OSArtifactSpec) DeepCopyInto(out *OSArtifactSpec) {
}
if in.CloudConfigRef != nil {
in, out := &in.CloudConfigRef, &out.CloudConfigRef
*out = new(SecretKeySelector)
**out = **in
*out = new(v1.SecretKeySelector)
(*in).DeepCopyInto(*out)
}
if in.Bundles != nil {
in, out := &in.Bundles, &out.Bundles
@ -109,9 +157,9 @@ func (in *OSArtifactSpec) DeepCopyInto(out *OSArtifactSpec) {
(*out)[key] = val
}
}
if in.OutputImage != nil {
in, out := &in.OutputImage, &out.OutputImage
*out = new(OutputImage)
if in.Exporter != nil {
in, out := &in.Exporter, &out.Exporter
*out = new(ExporterSpec)
(*in).DeepCopyInto(*out)
}
}
@ -131,7 +179,7 @@ func (in *OSArtifactStatus) DeepCopyInto(out *OSArtifactStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]v1.Condition, len(*in))
*out = make([]metav1.Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
@ -149,36 +197,22 @@ func (in *OSArtifactStatus) DeepCopy() *OSArtifactStatus {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *OutputImage) DeepCopyInto(out *OutputImage) {
func (in *RegistrySpec) DeepCopyInto(out *RegistrySpec) {
*out = *in
out.Image = in.Image
if in.DockerConfigSecretKeyRef != nil {
in, out := &in.DockerConfigSecretKeyRef, &out.DockerConfigSecretKeyRef
*out = new(SecretKeySelector)
**out = **in
*out = new(v1.SecretKeySelector)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OutputImage.
func (in *OutputImage) DeepCopy() *OutputImage {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistrySpec.
func (in *RegistrySpec) DeepCopy() *RegistrySpec {
if in == nil {
return nil
}
out := new(OutputImage)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SecretKeySelector) DeepCopyInto(out *SecretKeySelector) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretKeySelector.
func (in *SecretKeySelector) DeepCopy() *SecretKeySelector {
if in == nil {
return nil
}
out := new(SecretKeySelector)
out := new(RegistrySpec)
in.DeepCopyInto(out)
return out
}

View File

@ -5,4 +5,4 @@ maintainers:
- name: Plural
email: support@plural.sh
type: application
version: 0.5.1
version: 0.6.0

View File

@ -22,13 +22,19 @@ spec:
cloudConfigRef:
name: {{ include "osartifact.fullname" . }}-config
key: cloud-config.yaml
outputImage:
cloud: {{ .Values.exporter.cloud }}
registry: {{ .Values.exporter.registry }}
repository: {{ .Values.exporter.repository }}
tag: {{ .Values.exporter.tag }}
{{- if (eq .Values.exporter.cloud "other") }}
passwordSecretKeyRef:
name: {{ .Values.exporter.configSecret.name | default (printf "%s-%s" (include "osartifact.fullname" .) "config") }}
key: {{ .Values.exporter.configSecret.key }}
{{- end }}
exporter:
serviceAccount: {{ include "osartifact.fullname" . }}
{{- with .Values.exporter.extraEnvVars }}
extraEnvVars: {{ . | toYaml | nindent 4 }}
{{- end }}
registry:
name: {{ .Values.exporter.registry.name }}
type: {{ .Values.exporter.registry.type }}
image:
repository: {{ .Values.exporter.registry.image.repository }}
tag: {{ .Values.exporter.registry.image.tag }}
{{- if (eq .Values.exporter.registry.type "other") }}
passwordSecretKeyRef:
name: {{ .Values.exporter.registry.configSecret.name | default (printf "%s-%s" (include "osartifact.fullname" .) "config") }}
key: {{ .Values.exporter.registry.configSecret.key }}
{{- end }}

View File

@ -95,7 +95,7 @@ stringData:
{
"auths": {
"{{ .Values.exporter.registry }}": {
"auth": {{ printf "%s:%s" .Values.exporter.username $dockerUserPassword | b64enc | quote }}
"auth": {{ printf "%s:%s" .Values.exporter.registry.username $dockerUserPassword | b64enc | quote }}
}
}
}

View File

@ -0,0 +1,9 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "osartifact.fullname" . }}
namespace: {{ .Release.Namespace }}
{{- with .Values.exporter.serviceAccount.annotations }}
annotations:
{{- . | toYaml | nindent 4 }}
{{- end }}

View File

@ -59,23 +59,34 @@ extraCloudConfig: ~
# Export configuration for the final ISO images
exporter:
# Whether container registry is an ECR instance or other. One of: "ecr", "other"
cloud: other
# Docker registry DNS name where we should export packed ISO images
registry: ~
# Name of the repository where images should be stored
repository: plural-edge
# Image tag that should be used when pushing to the registry
tag: latest
# Username used when generating docker config.json. It is only used when 'passwordSecret' is provided.
username: plural
# Secret that stores just the password for the docker registry user.
# One of 'passwordSecret' or 'configSecret' must be provided.
passwordSecret:
serviceAccount:
annotations: ~
# Defines extra env vars that will be added to the exporter pob
# extraEnvVars:
# - name: MY_ENV_VAR
# value: myvalue
extraEnvVars: []
registry:
# Container registry DNS name where we should export packed ISO images
name: ~
key: password
# Secret configuration that stores the docker config.json file with the auth information.
# It is in the default docker format.
configSecret:
name: ~
key: config.json
# Whether container registry is an ECR instance or other. One of: "ecr", "other"
type: other
image:
# Name of the repository where images should be stored
repository: plural-edge
# Image tag that should be used when pushing to the registry
tag: latest
# Username used when generating docker config.json. It is only used when 'passwordSecret' is provided.
username: plural
# Secret that stores just the password for the docker registry user.
# One of 'passwordSecret' or 'configSecret' must be provided.
passwordSecret:
name: ~
key: password
# Secret configuration that stores the docker config.json file with the auth information.
# It is in the default docker format.
configSecret:
name: ~
key: config.json

View File

@ -1,8 +1,8 @@
apiVersion: v2
name: osbuilder
description: A Helm chart for osbuilder
appVersion: 0.2.0
version: 0.1.13
appVersion: 0.3.0
version: 0.1.14
dependencies:
- name: cert-manager
version: v1.16.3

View File

@ -48,13 +48,226 @@ spec:
type: string
type: array
cloudConfigRef:
description: SecretKeySelector selects a key of a Secret.
properties:
key:
description: The key of the secret to select from. Must be a
valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret or its key must be defined
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
exporter:
description: |-
Exporter when provided it will spawn an exporter job that
pushes images built by the osbuilder to the provided registry.
properties:
extraEnvVars:
description: ExtraEnvVars allows to append extra env vars to the
exporter pods.
items:
description: EnvVar represents an environment variable present
in a Container.
properties:
name:
description: Name of the environment variable. Must be a
C_IDENTIFIER.
type: string
value:
description: |-
Variable references $(VAR_NAME) are expanded
using the previously defined environment variables in the container and
any service environment variables. If a variable cannot be resolved,
the reference in the input string will be unchanged. Double $$ are reduced
to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e.
"$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)".
Escaped references will never be expanded, regardless of whether the variable
exists or not.
Defaults to "".
type: string
valueFrom:
description: Source for the environment variable's value.
Cannot be used if value is not empty.
properties:
configMapKeyRef:
description: Selects a key of a ConfigMap.
properties:
key:
description: The key to select.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the ConfigMap or its
key must be defined
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
fieldRef:
description: |-
Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['<KEY>']`, `metadata.annotations['<KEY>']`,
spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.
properties:
apiVersion:
description: Version of the schema the FieldPath
is written in terms of, defaults to "v1".
type: string
fieldPath:
description: Path of the field to select in the
specified API version.
type: string
required:
- fieldPath
type: object
x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
(limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.
properties:
containerName:
description: 'Container name: required for volumes,
optional for env vars'
type: string
divisor:
anyOf:
- type: integer
- type: string
description: Specifies the output format of the
exposed resources, defaults to "1"
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
resource:
description: 'Required: resource to select'
type: string
required:
- resource
type: object
x-kubernetes-map-type: atomic
secretKeyRef:
description: Selects a key of a secret in the pod's
namespace
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret or its key
must be defined
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
type: object
required:
- name
type: object
type: array
registry:
description: Registry is a registry spec used to push the final
images built by the osbuilder.
properties:
dockerConfigSecretKeyRef:
description: |-
DockerConfigSecretKeyRef is a reference to the secret that holds the `config.json` auth file.
It should be in a format that `docker login` can accept to auth to the registry.
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret or its key must
be defined
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
image:
description: Image defines the image details required to push
image to the registry.
properties:
repository:
description: Repository is the name of repository where
image is being pushed.
type: string
tag:
description: Tag is the tag name of the image being pushed.
Defaults to 'latest' if not provided.
type: string
required:
- repository
type: object
name:
description: Name is a DNS name of the registry. It has to
be accessible by the pod.
type: string
type:
default: other
description: "Type is a kind of registry being used. Currently
supported values are:\n\t- ecr \t- Amazon Elastic Container
Registry. Use only if a pod runs on\n\t\t\t an eks cluster
and has permissions to push to the registry.\n\t- other
- Any other type of the registry. It requires DockerConfigSecretKeyRef\n\t\t\t
\ to be provided in order to auth to the registry."
enum:
- ecr
- other
type: string
required:
- image
- name
- type
type: object
serviceAccount:
description: ServiceAccount allows overriding 'default' SA bound
to the exporter pods.
type: string
required:
- name
- registry
type: object
fileBundles:
additionalProperties:
@ -70,32 +283,6 @@ spec:
- rpi3
- rpi4
type: string
outputImage:
properties:
cloud:
default: other
enum:
- ecr
- other
type: string
dockerConfigSecretKeyRef:
properties:
key:
type: string
name:
type: string
required:
- name
type: object
registry:
type: string
repository:
type: string
tag:
type: string
required:
- cloud
type: object
type: object
status:
description: OSArtifactStatus defines the observed state of OSArtifact

View File

@ -1,5 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: '{{ include "helm-chart.serviceAccountName" . }}'
namespace: '{{.Release.Namespace}}'
name: '{{ include "helm-chart.serviceAccountName" . }}'
namespace: '{{.Release.Namespace}}'

View File

@ -48,13 +48,226 @@ spec:
type: string
type: array
cloudConfigRef:
description: SecretKeySelector selects a key of a Secret.
properties:
key:
description: The key of the secret to select from. Must be a
valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret or its key must be defined
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
exporter:
description: |-
Exporter when provided it will spawn an exporter job that
pushes images built by the osbuilder to the provided registry.
properties:
extraEnvVars:
description: ExtraEnvVars allows to append extra env vars to the
exporter pods.
items:
description: EnvVar represents an environment variable present
in a Container.
properties:
name:
description: Name of the environment variable. Must be a
C_IDENTIFIER.
type: string
value:
description: |-
Variable references $(VAR_NAME) are expanded
using the previously defined environment variables in the container and
any service environment variables. If a variable cannot be resolved,
the reference in the input string will be unchanged. Double $$ are reduced
to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e.
"$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)".
Escaped references will never be expanded, regardless of whether the variable
exists or not.
Defaults to "".
type: string
valueFrom:
description: Source for the environment variable's value.
Cannot be used if value is not empty.
properties:
configMapKeyRef:
description: Selects a key of a ConfigMap.
properties:
key:
description: The key to select.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the ConfigMap or its
key must be defined
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
fieldRef:
description: |-
Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['<KEY>']`, `metadata.annotations['<KEY>']`,
spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.
properties:
apiVersion:
description: Version of the schema the FieldPath
is written in terms of, defaults to "v1".
type: string
fieldPath:
description: Path of the field to select in the
specified API version.
type: string
required:
- fieldPath
type: object
x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
(limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.
properties:
containerName:
description: 'Container name: required for volumes,
optional for env vars'
type: string
divisor:
anyOf:
- type: integer
- type: string
description: Specifies the output format of the
exposed resources, defaults to "1"
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
resource:
description: 'Required: resource to select'
type: string
required:
- resource
type: object
x-kubernetes-map-type: atomic
secretKeyRef:
description: Selects a key of a secret in the pod's
namespace
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret or its key
must be defined
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
type: object
required:
- name
type: object
type: array
registry:
description: Registry is a registry spec used to push the final
images built by the osbuilder.
properties:
dockerConfigSecretKeyRef:
description: |-
DockerConfigSecretKeyRef is a reference to the secret that holds the `config.json` auth file.
It should be in a format that `docker login` can accept to auth to the registry.
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret or its key must
be defined
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
image:
description: Image defines the image details required to push
image to the registry.
properties:
repository:
description: Repository is the name of repository where
image is being pushed.
type: string
tag:
description: Tag is the tag name of the image being pushed.
Defaults to 'latest' if not provided.
type: string
required:
- repository
type: object
name:
description: Name is a DNS name of the registry. It has to
be accessible by the pod.
type: string
type:
default: other
description: "Type is a kind of registry being used. Currently
supported values are:\n\t- ecr \t- Amazon Elastic Container
Registry. Use only if a pod runs on\n\t\t\t an eks cluster
and has permissions to push to the registry.\n\t- other
- Any other type of the registry. It requires DockerConfigSecretKeyRef\n\t\t\t
\ to be provided in order to auth to the registry."
enum:
- ecr
- other
type: string
required:
- image
- name
- type
type: object
serviceAccount:
description: ServiceAccount allows overriding 'default' SA bound
to the exporter pods.
type: string
required:
- name
- registry
type: object
fileBundles:
additionalProperties:
@ -70,32 +283,6 @@ spec:
- rpi3
- rpi4
type: string
outputImage:
properties:
cloud:
default: other
enum:
- ecr
- other
type: string
dockerConfigSecretKeyRef:
properties:
key:
type: string
name:
type: string
required:
- name
type: object
registry:
type: string
repository:
type: string
tag:
type: string
required:
- cloud
type: object
type: object
status:
description: OSArtifactStatus defines the observed state of OSArtifact

View File

@ -51,7 +51,7 @@ const (
artifactExporterIndexAnnotation = "build.kairos.io/export-index"
ready = "Ready"
)
const threeHours = int32(10800)
const threeHours = int32(3 * 60 * 60)
var (
requeue = ctrl.Result{RequeueAfter: requeueAfter}
@ -260,7 +260,7 @@ func (r *OSArtifactReconciler) checkExport(ctx context.Context, artifact *osbuil
return ctrl.Result{}, fmt.Errorf("failed to locate artifact pvc")
}
if artifact.Spec.OutputImage != nil {
if artifact.Spec.Exporter != nil {
idx := fmt.Sprintf("%d", 1)
job := indexedJobs[idx]
@ -280,7 +280,8 @@ func (r *OSArtifactReconciler) checkExport(ctx context.Context, artifact *osbuil
BackoffLimit: ptr(int32(1)),
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyOnFailure,
ServiceAccountName: artifact.Spec.Exporter.ServiceAccountName(),
RestartPolicy: corev1.RestartPolicyNever,
InitContainers: []corev1.Container{
{
Name: "init-container",
@ -303,13 +304,18 @@ func (r *OSArtifactReconciler) checkExport(ctx context.Context, artifact *osbuil
},
}
tag := artifact.Spec.Exporter.Registry.Image.Tag
if len(tag) == 0 {
tag = "latest"
}
container := corev1.Container{
Name: "exporter",
Image: "gcr.io/kaniko-project/executor:latest",
Args: []string{
"--context=/artifacts/",
"--dockerfile=/artifacts/Dockerfile",
fmt.Sprintf("--destination=%s/%s:%s", artifact.Spec.OutputImage.Registry, artifact.Spec.OutputImage.Repository, artifact.Spec.OutputImage.Tag),
fmt.Sprintf("--destination=%s/%s:%s", artifact.Spec.Exporter.Registry.Name, artifact.Spec.Exporter.Registry.Image.Repository, tag),
},
VolumeMounts: []corev1.VolumeMount{
{
@ -318,19 +324,30 @@ func (r *OSArtifactReconciler) checkExport(ctx context.Context, artifact *osbuil
SubPath: "artifacts",
},
},
Env: []corev1.EnvVar{},
}
if artifact.Spec.OutputImage != nil && artifact.Spec.OutputImage.Cloud == osbuilder.RegistryCloudECR {
container.Env = []corev1.EnvVar{
// Append EKS specific env vars if using ECR registry
if artifact.Spec.Exporter.IsECRRegistry() {
container.Env = append(container.Env, []corev1.EnvVar{
{Name: "AWS_SDK_LOAD_CONFIG", Value: "true"},
{Name: "AWS_EC2_METADATA_DISABLED", Value: "true"},
}
}...)
}
if artifact.Spec.OutputImage != nil && artifact.Spec.OutputImage.DockerConfigSecretKeyRef != nil {
if err := r.Get(ctx, client.ObjectKey{Namespace: artifact.Namespace, Name: artifact.Spec.OutputImage.DockerConfigSecretKeyRef.Name}, &corev1.Secret{}); err != nil {
// Append extra env vars
if artifact.Spec.Exporter.HasExtraEnvVars() {
container.Env = append(container.Env, *artifact.Spec.Exporter.ExtraEnvVars...)
}
// Mount custom config.json file from secret
if artifact.Spec.Exporter.HasDockerConfigSecret() {
name := artifact.Spec.Exporter.Registry.DockerConfigSecretKeyRef.Name
key := artifact.Spec.Exporter.Registry.DockerConfigSecretKeyRef.Key
if err := r.Get(ctx, client.ObjectKey{Namespace: artifact.Namespace, Name: name}, &corev1.Secret{}); err != nil {
if errors.IsNotFound(err) {
logger.Info(fmt.Sprintf("Secret %s/%s not found", artifact.Namespace, artifact.Spec.OutputImage.DockerConfigSecretKeyRef.Name))
logger.Info(fmt.Sprintf("Secret %s/%s not found", artifact.Namespace, name))
return requeue, nil
}
return ctrl.Result{}, err
@ -343,10 +360,10 @@ func (r *OSArtifactReconciler) checkExport(ctx context.Context, artifact *osbuil
Name: "docker-secret",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: artifact.Spec.OutputImage.DockerConfigSecretKeyRef.Name,
SecretName: name,
Items: []corev1.KeyToPath{{
Key: artifact.Spec.OutputImage.DockerConfigSecretKeyRef.Key,
Path: artifact.Spec.OutputImage.DockerConfigSecretKeyRef.Key,
Key: key,
Path: "config.json",
}},
},
},