diff --git a/packages/core/platform/bundles/distro-full.yaml b/packages/core/platform/bundles/distro-full.yaml index a74da8b16..984d0cb0b 100644 --- a/packages/core/platform/bundles/distro-full.yaml +++ b/packages/core/platform/bundles/distro-full.yaml @@ -199,3 +199,10 @@ releases: namespace: cozy-keycloak optional: true dependsOn: [keycloak] + +- name: tinkerbell + releaseName: tinkerbell + chart: cozy-tinkerbell + namespace: cozy-tinkerbell + optional: true + dependsOn: [cilium,kubeovn] diff --git a/packages/core/platform/bundles/paas-full.yaml b/packages/core/platform/bundles/paas-full.yaml index 6b73f6ef0..bc5368d44 100644 --- a/packages/core/platform/bundles/paas-full.yaml +++ b/packages/core/platform/bundles/paas-full.yaml @@ -281,6 +281,13 @@ releases: optional: true dependsOn: [cilium,kubeovn] +- name: tinkerbell + releaseName: tinkerbell + chart: cozy-tinkerbell + namespace: cozy-tinkerbell + optional: true + dependsOn: [cilium,kubeovn] + {{- if $oidcEnabled }} - name: keycloak releaseName: keycloak diff --git a/packages/system/tinkerbell/Chart.yaml b/packages/system/tinkerbell/Chart.yaml new file mode 100644 index 000000000..efb26935f --- /dev/null +++ b/packages/system/tinkerbell/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: cozy-tinkerbell +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/tinkerbell/Makefile b/packages/system/tinkerbell/Makefile new file mode 100644 index 000000000..ccdcdd2a4 --- /dev/null +++ b/packages/system/tinkerbell/Makefile @@ -0,0 +1,16 @@ +export NAME=tinkerbell +export NAMESPACE=cozy-$(NAME) + +include ../../../scripts/package.mk + +update: + rm -rf charts + mkdir -p charts + cd charts && \ + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/tinkerbell/charts | awk -F'[/^]' 'END{print $$3}') && \ + curl -sSL https://github.com/tinkerbell/charts/archive/refs/tags/$${tag}.tar.gz | \ + tar xzvf - --strip 2 charts-$${tag#*v}/tinkerbell + find charts -maxdepth 1 -mindepth 1 ! -name tink -and ! -name smee -and ! -name rufio -exec rm -rf {} \; + mkdir -p charts/smee/crds + mv charts/tink/crds/hardware-crd.yaml charts/smee/crds + rm -rf charts/tink diff --git a/packages/system/tinkerbell/charts/rufio/Chart.yaml b/packages/system/tinkerbell/charts/rufio/Chart.yaml new file mode 100644 index 000000000..c6c1b337c --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/Chart.yaml @@ -0,0 +1,25 @@ +apiVersion: v2 +name: rufio +description: Rufio handles BMC interactions for Tinkerbell +icon: https://github.com/tinkerbell/artwork/blob/6f07de53d75cb8932dbc7d14201e038cf3a3b230/Tinkerbell-Icon-Dark.png + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.4.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "0.6.1" diff --git a/packages/system/tinkerbell/charts/rufio/crds/bmc.tinkerbell.org_jobs.yaml b/packages/system/tinkerbell/charts/rufio/crds/bmc.tinkerbell.org_jobs.yaml new file mode 100644 index 000000000..e5b964537 --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/crds/bmc.tinkerbell.org_jobs.yaml @@ -0,0 +1,166 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: jobs.bmc.tinkerbell.org +spec: + group: bmc.tinkerbell.org + names: + categories: + - tinkerbell + kind: Job + listKind: JobList + plural: jobs + shortNames: + - j + singular: job + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Job is the Schema for the bmcjobs API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: JobSpec defines the desired state of Job. + properties: + machineRef: + description: |- + MachineRef represents the Machine resource to execute the job. + All the tasks in the job are executed for the same Machine. + properties: + name: + description: Name of the Machine. + type: string + namespace: + description: Namespace the Machine resides in. + type: string + required: + - name + - namespace + type: object + tasks: + description: |- + Tasks represents a list of baseboard management actions to be executed. + The tasks are executed sequentially. Controller waits for one task to complete before executing the next. + If a single task fails, job execution stops and sets condition Failed. + Condition Completed is set only if all the tasks were successful. + items: + description: |- + Action represents the action to be performed. + A single task can only perform one type of action. + For example either PowerAction or OneTimeBootDeviceAction. + maxProperties: 1 + properties: + oneTimeBootDeviceAction: + description: OneTimeBootDeviceAction represents a baseboard + management one time set boot device operation. + properties: + device: + description: |- + Devices represents the boot devices, in order for setting one time boot. + Currently only the first device in the slice is used to set one time boot. + items: + description: BootDevice represents boot device of the + Machine. + type: string + type: array + efiBoot: + description: EFIBoot instructs the machine to use EFI boot. + type: boolean + required: + - device + type: object + powerAction: + description: PowerAction represents a baseboard management power + operation. + enum: + - "on" + - "off" + - soft + - status + - cycle + - reset + type: string + virtualMediaAction: + description: VirtualMediaAction represents a baseboard management + virtual media insert/eject. + properties: + kind: + type: string + mediaURL: + description: |- + mediaURL represents the URL of the image to be inserted into the virtual media, or empty to + eject media. + type: string + required: + - kind + type: object + type: object + minItems: 1 + type: array + required: + - machineRef + - tasks + type: object + status: + description: JobStatus defines the observed state of Job. + properties: + completionTime: + description: |- + CompletionTime represents time when the job was completed. + The completion time is only set when the job finishes successfully. + format: date-time + type: string + conditions: + description: Conditions represents the latest available observations + of an object's current state. + items: + properties: + message: + description: Message represents human readable message indicating + details about last transition. + type: string + status: + description: |- + Status is the status of the Job condition. + Can be True or False. + type: string + type: + description: Type of the Job condition. + type: string + required: + - status + - type + type: object + type: array + startTime: + description: StartTime represents time when the Job controller started + processing a job. + format: date-time + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/tinkerbell/charts/rufio/crds/bmc.tinkerbell.org_machines.yaml b/packages/system/tinkerbell/charts/rufio/crds/bmc.tinkerbell.org_machines.yaml new file mode 100644 index 000000000..3e49c84b8 --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/crds/bmc.tinkerbell.org_machines.yaml @@ -0,0 +1,294 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: machines.bmc.tinkerbell.org +spec: + group: bmc.tinkerbell.org + names: + categories: + - tinkerbell + kind: Machine + listKind: MachineList + plural: machines + singular: machine + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Machine is the Schema for the machines API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: MachineSpec defines desired machine state. + properties: + connection: + description: Connection contains connection data for a Baseboard Management + Controller. + properties: + authSecretRef: + description: |- + AuthSecretRef is the SecretReference that contains authentication information of the Machine. + The Secret must contain username and password keys. This is optional as it is not required when using + the RPC provider. + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + host: + description: Host is the host IP address or hostname of the Machine. + minLength: 1 + type: string + insecureTLS: + description: InsecureTLS specifies trusted TLS connections. + type: boolean + port: + default: 623 + description: Port is the port number for connecting with the Machine. + type: integer + providerOptions: + description: ProviderOptions contains provider specific options. + properties: + intelAMT: + description: IntelAMT contains the options to customize the + IntelAMT provider. + properties: + hostScheme: + default: http + description: HostScheme determines whether to use http + or https for intelAMT calls. + enum: + - http + - https + type: string + port: + description: Port that intelAMT will use for calls. + type: integer + type: object + ipmitool: + description: IPMITOOL contains the options to customize the + Ipmitool provider. + properties: + cipherSuite: + description: CipherSuite that ipmitool will use for calls. + type: string + port: + description: Port that ipmitool will use for calls. + type: integer + type: object + preferredOrder: + description: |- + PreferredOrder allows customizing the order that BMC providers are called. + Providers added to this list will be moved to the front of the default order. + Provider names are case insensitive. + The default order is: ipmitool, asrockrack, gofish, intelamt, dell, supermicro, openbmc. + items: + description: ProviderName is the bmclib specific provider + name. Names are case insensitive. + pattern: (?i)^(ipmitool|asrockrack|gofish|IntelAMT|dell|supermicro|openbmc)$ + type: string + type: array + redfish: + description: Redfish contains the options to customize the + Redfish provider. + properties: + port: + description: Port that redfish will use for calls. + type: integer + systemName: + description: |- + SystemName is the name of the system to use for redfish calls. + With redfish implementations that manage multiple systems via a single endpoint, this allows for specifying the system to manage. + type: string + useBasicAuth: + description: UseBasicAuth for redfish calls. The default + is false which means token based auth is used. + type: boolean + type: object + rpc: + description: RPC contains the options to customize the RPC + provider. + properties: + consumerURL: + description: |- + ConsumerURL is the URL where an rpc consumer/listener is running + and to which we will send and receive all notifications. + type: string + experimental: + description: Experimental options. + properties: + customRequestPayload: + description: CustomRequestPayload must be in json. + type: string + dotPath: + description: 'DotPath is the path to the json object + where the bmclib RequestPayload{} struct will be + embedded. For example: object.data.body' + type: string + type: object + hmac: + description: HMAC is the options used to create a HMAC + signature. + properties: + prefixSigDisabled: + description: 'PrefixSigDisabled determines whether + the algorithm will be prefixed to the signature. + Example: sha256=abc123' + type: boolean + secrets: + additionalProperties: + items: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace + to reference a secret resource. + type: string + namespace: + description: namespace defines the space within + which the secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + type: array + description: Secrets are a map of algorithms to secrets + used for signing. + type: object + type: object + logNotificationsDisabled: + description: LogNotificationsDisabled determines whether + responses from rpc consumer/listeners will be logged + or not. + type: boolean + request: + description: Request is the options used to create the + rpc HTTP request. + properties: + httpContentType: + description: HTTPContentType is the content type to + use for the rpc request notification. + type: string + httpMethod: + description: HTTPMethod is the HTTP method to use + for the rpc request notification. + type: string + staticHeaders: + additionalProperties: + items: + type: string + type: array + description: StaticHeaders are predefined headers + that will be added to every request. + type: object + timestampFormat: + description: TimestampFormat is the time format for + the timestamp header. + type: string + timestampHeader: + description: 'TimestampHeader is the header name that + should contain the timestamp. Example: X-BMCLIB-Timestamp' + type: string + type: object + signature: + description: Signature is the options used for adding + an HMAC signature to an HTTP request. + properties: + appendAlgoToHeaderDisabled: + description: |- + AppendAlgoToHeaderDisabled decides whether to append the algorithm to the signature header or not. + Example: X-BMCLIB-Signature becomes X-BMCLIB-Signature-256 + When set to true, a header will be added for each algorithm. Example: X-BMCLIB-Signature-256 and X-BMCLIB-Signature-512 + type: boolean + headerName: + description: 'HeaderName is the header name that should + contain the signature(s). Example: X-BMCLIB-Signature' + type: string + includedPayloadHeaders: + description: |- + IncludedPayloadHeaders are headers whose values will be included in the signature payload. Example: X-BMCLIB-My-Custom-Header + All headers will be deduplicated. + items: + type: string + type: array + type: object + required: + - consumerURL + type: object + type: object + required: + - host + - insecureTLS + type: object + required: + - connection + type: object + status: + description: MachineStatus defines the observed state of Machine. + properties: + conditions: + description: Conditions represents the latest available observations + of an object's current state. + items: + description: MachineCondition defines an observed condition of a + Machine. + properties: + lastUpdateTime: + description: LastUpdateTime of the condition. + format: date-time + type: string + message: + description: Message is a human readable message indicating + with details of the last transition. + type: string + status: + description: Status of the condition. + type: string + type: + description: Type of the Machine condition. + type: string + required: + - status + - type + type: object + type: array + powerState: + description: Power is the current power state of the Machine. + enum: + - "on" + - "off" + - unknown + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/tinkerbell/charts/rufio/crds/bmc.tinkerbell.org_tasks.yaml b/packages/system/tinkerbell/charts/rufio/crds/bmc.tinkerbell.org_tasks.yaml new file mode 100644 index 000000000..d2bc904fb --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/crds/bmc.tinkerbell.org_tasks.yaml @@ -0,0 +1,342 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: tasks.bmc.tinkerbell.org +spec: + group: bmc.tinkerbell.org + names: + categories: + - tinkerbell + kind: Task + listKind: TaskList + plural: tasks + shortNames: + - t + singular: task + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Task is the Schema for the Task API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: TaskSpec defines the desired state of Task. + properties: + connection: + description: Connection represents the Machine connectivity information. + properties: + authSecretRef: + description: |- + AuthSecretRef is the SecretReference that contains authentication information of the Machine. + The Secret must contain username and password keys. This is optional as it is not required when using + the RPC provider. + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + host: + description: Host is the host IP address or hostname of the Machine. + minLength: 1 + type: string + insecureTLS: + description: InsecureTLS specifies trusted TLS connections. + type: boolean + port: + default: 623 + description: Port is the port number for connecting with the Machine. + type: integer + providerOptions: + description: ProviderOptions contains provider specific options. + properties: + intelAMT: + description: IntelAMT contains the options to customize the + IntelAMT provider. + properties: + hostScheme: + default: http + description: HostScheme determines whether to use http + or https for intelAMT calls. + enum: + - http + - https + type: string + port: + description: Port that intelAMT will use for calls. + type: integer + type: object + ipmitool: + description: IPMITOOL contains the options to customize the + Ipmitool provider. + properties: + cipherSuite: + description: CipherSuite that ipmitool will use for calls. + type: string + port: + description: Port that ipmitool will use for calls. + type: integer + type: object + preferredOrder: + description: |- + PreferredOrder allows customizing the order that BMC providers are called. + Providers added to this list will be moved to the front of the default order. + Provider names are case insensitive. + The default order is: ipmitool, asrockrack, gofish, intelamt, dell, supermicro, openbmc. + items: + description: ProviderName is the bmclib specific provider + name. Names are case insensitive. + pattern: (?i)^(ipmitool|asrockrack|gofish|IntelAMT|dell|supermicro|openbmc)$ + type: string + type: array + redfish: + description: Redfish contains the options to customize the + Redfish provider. + properties: + port: + description: Port that redfish will use for calls. + type: integer + systemName: + description: |- + SystemName is the name of the system to use for redfish calls. + With redfish implementations that manage multiple systems via a single endpoint, this allows for specifying the system to manage. + type: string + useBasicAuth: + description: UseBasicAuth for redfish calls. The default + is false which means token based auth is used. + type: boolean + type: object + rpc: + description: RPC contains the options to customize the RPC + provider. + properties: + consumerURL: + description: |- + ConsumerURL is the URL where an rpc consumer/listener is running + and to which we will send and receive all notifications. + type: string + experimental: + description: Experimental options. + properties: + customRequestPayload: + description: CustomRequestPayload must be in json. + type: string + dotPath: + description: 'DotPath is the path to the json object + where the bmclib RequestPayload{} struct will be + embedded. For example: object.data.body' + type: string + type: object + hmac: + description: HMAC is the options used to create a HMAC + signature. + properties: + prefixSigDisabled: + description: 'PrefixSigDisabled determines whether + the algorithm will be prefixed to the signature. + Example: sha256=abc123' + type: boolean + secrets: + additionalProperties: + items: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace + to reference a secret resource. + type: string + namespace: + description: namespace defines the space within + which the secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + type: array + description: Secrets are a map of algorithms to secrets + used for signing. + type: object + type: object + logNotificationsDisabled: + description: LogNotificationsDisabled determines whether + responses from rpc consumer/listeners will be logged + or not. + type: boolean + request: + description: Request is the options used to create the + rpc HTTP request. + properties: + httpContentType: + description: HTTPContentType is the content type to + use for the rpc request notification. + type: string + httpMethod: + description: HTTPMethod is the HTTP method to use + for the rpc request notification. + type: string + staticHeaders: + additionalProperties: + items: + type: string + type: array + description: StaticHeaders are predefined headers + that will be added to every request. + type: object + timestampFormat: + description: TimestampFormat is the time format for + the timestamp header. + type: string + timestampHeader: + description: 'TimestampHeader is the header name that + should contain the timestamp. Example: X-BMCLIB-Timestamp' + type: string + type: object + signature: + description: Signature is the options used for adding + an HMAC signature to an HTTP request. + properties: + appendAlgoToHeaderDisabled: + description: |- + AppendAlgoToHeaderDisabled decides whether to append the algorithm to the signature header or not. + Example: X-BMCLIB-Signature becomes X-BMCLIB-Signature-256 + When set to true, a header will be added for each algorithm. Example: X-BMCLIB-Signature-256 and X-BMCLIB-Signature-512 + type: boolean + headerName: + description: 'HeaderName is the header name that should + contain the signature(s). Example: X-BMCLIB-Signature' + type: string + includedPayloadHeaders: + description: |- + IncludedPayloadHeaders are headers whose values will be included in the signature payload. Example: X-BMCLIB-My-Custom-Header + All headers will be deduplicated. + items: + type: string + type: array + type: object + required: + - consumerURL + type: object + type: object + required: + - host + - insecureTLS + type: object + task: + description: Task defines the specific action to be performed. + maxProperties: 1 + properties: + oneTimeBootDeviceAction: + description: OneTimeBootDeviceAction represents a baseboard management + one time set boot device operation. + properties: + device: + description: |- + Devices represents the boot devices, in order for setting one time boot. + Currently only the first device in the slice is used to set one time boot. + items: + description: BootDevice represents boot device of the Machine. + type: string + type: array + efiBoot: + description: EFIBoot instructs the machine to use EFI boot. + type: boolean + required: + - device + type: object + powerAction: + description: PowerAction represents a baseboard management power + operation. + enum: + - "on" + - "off" + - soft + - status + - cycle + - reset + type: string + virtualMediaAction: + description: VirtualMediaAction represents a baseboard management + virtual media insert/eject. + properties: + kind: + type: string + mediaURL: + description: |- + mediaURL represents the URL of the image to be inserted into the virtual media, or empty to + eject media. + type: string + required: + - kind + type: object + type: object + required: + - task + type: object + status: + description: TaskStatus defines the observed state of Task. + properties: + completionTime: + description: |- + CompletionTime represents time when the task was completed. + The completion time is only set when the task finishes successfully. + format: date-time + type: string + conditions: + description: Conditions represents the latest available observations + of an object's current state. + items: + properties: + message: + description: Message represents human readable message indicating + details about last transition. + type: string + status: + description: |- + Status is the status of the Task condition. + Can be True or False. + type: string + type: + description: Type of the Task condition. + type: string + required: + - status + - type + type: object + type: array + startTime: + description: StartTime represents time when the Task started processing. + format: date-time + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/tinkerbell/charts/rufio/templates/_scheduling.tpl b/packages/system/tinkerbell/charts/rufio/templates/_scheduling.tpl new file mode 100644 index 000000000..395860de4 --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/templates/_scheduling.tpl @@ -0,0 +1,12 @@ +{{- define "singleNodeClusterConfig" }} +- effect: NoSchedule + key: node-role.kubernetes.io/control-plane +{{- end }} + +{{- define "preferWorkerNodes" }} +- weight: {{ .nodeAffinityWeight }} + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist +{{- end }} diff --git a/packages/system/tinkerbell/charts/rufio/templates/deployment.yaml b/packages/system/tinkerbell/charts/rufio/templates/deployment.yaml new file mode 100644 index 000000000..2073fa399 --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/templates/deployment.yaml @@ -0,0 +1,87 @@ +{{- if .Values.deploy }} +{{- $roleType := .Values.rbac.type }} +{{- $nodeSelector := .Values.nodeSelector }} +{{- if .Values.global }} +{{- $roleType = coalesce .Values.global.rbac.type .Values.rbac.type }} +{{- $nodeSelector = coalesce .Values.nodeSelector .Values.global.nodeSelector }} +{{- end }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: {{ .Values.name }} + control-plane: controller-manager + name: {{ .Values.name }} + namespace: {{ .Release.Namespace | quote }} +spec: + selector: + matchLabels: + app: {{ .Values.name }} + control-plane: controller-manager + stack: tinkerbell + replicas: 1 + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: manager + labels: + app: {{ .Values.name }} + control-plane: controller-manager + stack: tinkerbell + spec: + {{- if .Values.hostNetwork }} + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + {{- end }} + securityContext: + runAsNonRoot: true + containers: + - name: manager + image: {{ .Values.image }} + imagePullPolicy: {{ .Values.imagePullPolicy }} + command: + - /manager + args: + - --leader-elect + {{- if eq $roleType "Role" }} + - -kube-namespace={{ .Release.Namespace }} + {{- end }} + {{- range .Values.additionalArgs }} + - {{ . }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: {{ .Values.resources.limits.cpu }} + memory: {{ .Values.resources.limits.memory }} + requests: + cpu: {{ .Values.resources.requests.cpu }} + memory: {{ .Values.resources.requests.memory }} + serviceAccountName: {{ .Values.serviceAccountName }} + terminationGracePeriodSeconds: 10 + {{- with $nodeSelector }} + nodeSelector: + {{ toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.singleNodeClusterConfig.controlPlaneTolerationsEnabled }} + tolerations: + {{- include "singleNodeClusterConfig" . | indent 6 }} + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + {{- include "preferWorkerNodes" (dict "nodeAffinityWeight" .Values.singleNodeClusterConfig.nodeAffinityWeight) | indent 10 }} + {{- end }} +{{- end }} diff --git a/packages/system/tinkerbell/charts/rufio/templates/leader-election-role-binding.yaml b/packages/system/tinkerbell/charts/rufio/templates/leader-election-role-binding.yaml new file mode 100644 index 000000000..1d3588dd1 --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/templates/leader-election-role-binding.yaml @@ -0,0 +1,15 @@ +{{- if .Values.deploy }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ .Values.rufioLeaderElectionRoleBindingName }} + namespace: {{ .Release.Namespace | quote }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ .Values.rufioLeaderElectionRoleName }} +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccountName }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/packages/system/tinkerbell/charts/rufio/templates/leader-election-role.yaml b/packages/system/tinkerbell/charts/rufio/templates/leader-election-role.yaml new file mode 100644 index 000000000..ca1c5db0f --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/templates/leader-election-role.yaml @@ -0,0 +1,39 @@ +{{- if .Values.deploy }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ .Values.rufioLeaderElectionRoleName }} + namespace: {{ .Release.Namespace | quote }} +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +{{- end }} diff --git a/packages/system/tinkerbell/charts/rufio/templates/role-binding.yaml b/packages/system/tinkerbell/charts/rufio/templates/role-binding.yaml new file mode 100644 index 000000000..6867fee8c --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/templates/role-binding.yaml @@ -0,0 +1,21 @@ +{{- if .Values.deploy }} +{{- $roleType := .Values.rbac.type }} +{{- if .Values.global }} +{{- $roleType = coalesce .Values.global.rbac.type .Values.rbac.type }} +{{- end }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: {{ printf "%sBinding" $roleType }} +metadata: + name: {{ .Values.rbac.bindingName }} + {{- if eq $roleType "Role" }} + namespace: {{ .Release.Namespace | quote }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: {{ $roleType }} + name: {{ .Values.rbac.name }} +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccountName }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/packages/system/tinkerbell/charts/rufio/templates/role.yaml b/packages/system/tinkerbell/charts/rufio/templates/role.yaml new file mode 100644 index 000000000..464c5940c --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/templates/role.yaml @@ -0,0 +1,23 @@ +{{- if .Values.deploy }} +{{- $roleType := .Values.rbac.type }} +{{- if .Values.global }} +{{- $roleType = coalesce .Values.global.rbac.type .Values.rbac.type }} +{{- end }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: {{ $roleType }} +metadata: + name: {{ .Values.rbac.name }} + {{- if eq $roleType "Role" }} + namespace: {{ .Release.Namespace | quote }} + {{- end }} +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] +- apiGroups: ["bmc.tinkerbell.org"] + resources: ["jobs", "jobs/status", "machines", "machines/status", "tasks", "tasks/status"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] +- apiGroups: ["bmc.tinkerbell.org"] + resources: ["jobs/finalizers", "machines/finalizers", "tasks/finalizers"] + verbs: ["update"] +{{- end }} diff --git a/packages/system/tinkerbell/charts/rufio/templates/service-account.yaml b/packages/system/tinkerbell/charts/rufio/templates/service-account.yaml new file mode 100644 index 000000000..049742b2a --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/templates/service-account.yaml @@ -0,0 +1,7 @@ +{{- if .Values.deploy }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccountName }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/packages/system/tinkerbell/charts/rufio/values.schema.json b/packages/system/tinkerbell/charts/rufio/values.schema.json new file mode 100644 index 000000000..995856cf7 --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/values.schema.json @@ -0,0 +1,21 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "rbac": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["Role", "ClusterRole"] + }, + "name": { + "type": "string" + }, + "bindingName": { + "type": "string" + } + } + } + } + } diff --git a/packages/system/tinkerbell/charts/rufio/values.yaml b/packages/system/tinkerbell/charts/rufio/values.yaml new file mode 100644 index 000000000..13bdfaf9f --- /dev/null +++ b/packages/system/tinkerbell/charts/rufio/values.yaml @@ -0,0 +1,26 @@ +deploy: true +name: rufio +image: quay.io/tinkerbell/rufio:v0.6.1 +imagePullPolicy: IfNotPresent +resources: + requests: + cpu: 10m + memory: 64Mi + limits: + cpu: 500m + memory: 128Mi +additionalArgs: [] +serviceAccountName: rufio-controller-manager +rufioLeaderElectionRoleName: rufio-leader-election-role +rufioLeaderElectionRoleBindingName: rufio-leader-election-rolebinding +nodeSelector: {} +hostNetwork: false +# singleNodeClusterConfig to add tolerations for deployments on control plane nodes. This is defaulted to false. +singleNodeClusterConfig: + controlPlaneTolerationsEnabled: false + nodeAffinityWeight: 1 + +rbac: + type: Role # or ClusterRole + name: rufio-role # or rufio-cluster-role + bindingName: rufio-rolebinding # or rufio-cluster-rolebinding diff --git a/packages/system/tinkerbell/charts/smee/Chart.yaml b/packages/system/tinkerbell/charts/smee/Chart.yaml new file mode 100644 index 000000000..93b673061 --- /dev/null +++ b/packages/system/tinkerbell/charts/smee/Chart.yaml @@ -0,0 +1,25 @@ +apiVersion: v2 +name: smee +description: Smee is the network boot service for Tinkerbell +icon: https://github.com/tinkerbell/artwork/blob/6f07de53d75cb8932dbc7d14201e038cf3a3b230/Tinkerbell-Icon-Dark.png + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.6.2 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "0.15.1" diff --git a/packages/system/tinkerbell/charts/smee/crds/hardware-crd.yaml b/packages/system/tinkerbell/charts/smee/crds/hardware-crd.yaml new file mode 100644 index 000000000..a32dcfbf0 --- /dev/null +++ b/packages/system/tinkerbell/charts/smee/crds/hardware-crd.yaml @@ -0,0 +1,388 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.3 + name: hardware.tinkerbell.org +spec: + group: tinkerbell.org + names: + categories: + - tinkerbell + kind: Hardware + listKind: HardwareList + plural: hardware + shortNames: + - hw + singular: hardware + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.state + name: State + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: Hardware is the Schema for the Hardware API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: HardwareSpec defines the desired state of Hardware. + properties: + bmcRef: + description: |- + BMCRef contains a relation to a BMC state management type in the same + namespace as the Hardware. This may be used for BMC management by + orchestrators. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + disks: + items: + description: Disk represents a disk device for Tinkerbell Hardware. + properties: + device: + type: string + type: object + type: array + interfaces: + items: + description: Interface represents a network interface configuration for Hardware. + properties: + dhcp: + description: DHCP configuration. + properties: + arch: + type: string + hostname: + type: string + iface_name: + type: string + ip: + description: IP configuration. + properties: + address: + type: string + family: + format: int64 + type: integer + gateway: + type: string + netmask: + type: string + type: object + lease_time: + format: int64 + type: integer + mac: + pattern: ([0-9a-f]{2}[:]){5}([0-9a-f]{2}) + type: string + name_servers: + items: + type: string + type: array + time_servers: + items: + type: string + type: array + uefi: + type: boolean + vlan_id: + description: validation pattern for VLANDID is a string number between 0-4096 + pattern: ^(([0-9][0-9]{0,2}|[1-3][0-9][0-9][0-9]|40([0-8][0-9]|9[0-6]))(,[1-9][0-9]{0,2}|[1-3][0-9][0-9][0-9]|40([0-8][0-9]|9[0-6]))*)$ + type: string + type: object + disableDhcp: + default: false + description: DisableDHCP disables DHCP for this interface. + type: boolean + netboot: + description: Netboot configuration. + properties: + allowPXE: + type: boolean + allowWorkflow: + type: boolean + ipxe: + description: IPXE configuration. + properties: + contents: + type: string + url: + type: string + type: object + osie: + description: OSIE configuration. + properties: + baseURL: + type: string + initrd: + type: string + kernel: + type: string + type: object + type: object + type: object + type: array + metadata: + properties: + bonding_mode: + format: int64 + type: integer + custom: + properties: + preinstalled_operating_system_version: + properties: + distro: + type: string + image_tag: + type: string + os_slug: + type: string + slug: + type: string + version: + type: string + type: object + private_subnets: + items: + type: string + type: array + type: object + facility: + properties: + facility_code: + type: string + plan_slug: + type: string + plan_version_slug: + type: string + type: object + instance: + properties: + allow_pxe: + type: boolean + always_pxe: + type: boolean + crypted_root_password: + type: string + hostname: + type: string + id: + type: string + ips: + items: + properties: + address: + type: string + family: + format: int64 + type: integer + gateway: + type: string + management: + type: boolean + netmask: + type: string + public: + type: boolean + type: object + type: array + ipxe_script_url: + type: string + network_ready: + type: boolean + operating_system: + properties: + distro: + type: string + image_tag: + type: string + os_slug: + type: string + slug: + type: string + version: + type: string + type: object + rescue: + type: boolean + ssh_keys: + items: + type: string + type: array + state: + type: string + storage: + properties: + disks: + items: + properties: + device: + type: string + partitions: + items: + properties: + label: + type: string + number: + format: int64 + type: integer + size: + format: int64 + type: integer + start: + format: int64 + type: integer + type_guid: + type: string + type: object + type: array + wipe_table: + type: boolean + type: object + type: array + filesystems: + items: + properties: + mount: + properties: + create: + properties: + force: + type: boolean + options: + items: + type: string + type: array + type: object + device: + type: string + files: + items: + properties: + contents: + type: string + gid: + format: int64 + type: integer + mode: + format: int64 + type: integer + path: + type: string + uid: + format: int64 + type: integer + type: object + type: array + format: + type: string + point: + type: string + type: object + type: object + type: array + raid: + items: + properties: + devices: + items: + type: string + type: array + level: + type: string + name: + type: string + spare: + format: int64 + type: integer + type: object + type: array + type: object + tags: + items: + type: string + type: array + userdata: + type: string + type: object + manufacturer: + properties: + id: + type: string + slug: + type: string + type: object + state: + type: string + type: object + resources: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Resources represents known resources that are available on a machine. + Resources may be used for scheduling by orchestrators. + type: object + tinkVersion: + format: int64 + type: integer + userData: + description: |- + UserData is the user data to configure in the hardware's + metadata + type: string + vendorData: + description: |- + VendorData is the vendor data to configure in the hardware's + metadata + type: string + type: object + status: + description: HardwareStatus defines the observed state of Hardware. + properties: + state: + description: HardwareState represents the hardware state. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/tinkerbell/charts/smee/templates/_ports.tpl b/packages/system/tinkerbell/charts/smee/templates/_ports.tpl new file mode 100644 index 000000000..aab0ea249 --- /dev/null +++ b/packages/system/tinkerbell/charts/smee/templates/_ports.tpl @@ -0,0 +1,24 @@ +{{ define "smee.ports" }} +- {{ .PortKey }}: {{ .http.port }} + name: {{ .http.name }} + protocol: TCP +- {{ .PortKey }}: {{ .syslog.port }} + name: {{ .syslog.name }} + protocol: UDP +- {{ .PortKey }}: {{ .dhcp.port }} + name: {{ .dhcp.name }} + protocol: UDP +- {{ .PortKey }}: {{ .tftp.port }} + name: {{ .tftp.name }} + protocol: UDP +{{- end }} + +{{- define "urlJoiner" }} +{{- if .urlDict.port }} +{{- $host := printf "%v:%v" .urlDict.host .urlDict.port }} +{{- $newDict := set .urlDict "host" $host }} +{{- print (urlJoin $newDict) }} +{{- else }} +{{- print (urlJoin .urlDict) }} +{{- end }} +{{- end }} diff --git a/packages/system/tinkerbell/charts/smee/templates/_scheduling.tpl b/packages/system/tinkerbell/charts/smee/templates/_scheduling.tpl new file mode 100644 index 000000000..395860de4 --- /dev/null +++ b/packages/system/tinkerbell/charts/smee/templates/_scheduling.tpl @@ -0,0 +1,12 @@ +{{- define "singleNodeClusterConfig" }} +- effect: NoSchedule + key: node-role.kubernetes.io/control-plane +{{- end }} + +{{- define "preferWorkerNodes" }} +- weight: {{ .nodeAffinityWeight }} + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: DoesNotExist +{{- end }} diff --git a/packages/system/tinkerbell/charts/smee/templates/deployment.yaml b/packages/system/tinkerbell/charts/smee/templates/deployment.yaml new file mode 100644 index 000000000..9f099c3ff --- /dev/null +++ b/packages/system/tinkerbell/charts/smee/templates/deployment.yaml @@ -0,0 +1,182 @@ +{{- if .Values.deploy }} +{{- $publicIP := .Values.publicIP }} +{{- $trustedProxies := .Values.trustedProxies }} +{{- $roleType := .Values.rbac.type }} +{{- $nodeSelector := .Values.nodeSelector }} +{{- if .Values.global }} +{{- $publicIP = coalesce .Values.publicIP .Values.global.publicIP }} +{{- $trustedProxies = coalesce .Values.trustedProxies .Values.global.trustedProxies }} +{{- $roleType = coalesce .Values.global.rbac.type .Values.rbac.type }} +{{- $nodeSelector = coalesce .Values.nodeSelector .Values.global.nodeSelector }} +{{- end }} +{{- $_ := set .Values.dhcp "syslogIp" (default $publicIP .Values.dhcp.syslogIp) }} +{{- $_ := set .Values.dhcp "ipForPacket" (default $publicIP .Values.dhcp.ipForPacket) }} +{{- $_ := set .Values.dhcp "tftpIp" (default $publicIP .Values.dhcp.tftpIp) }} +{{- $_ := set .Values.dhcp.httpIPXE.binaryUrl "host" (default $publicIP .Values.dhcp.httpIPXE.binaryUrl.host) }} +{{- $_ := set .Values.dhcp.httpIPXE.scriptUrl "host" (default $publicIP .Values.dhcp.httpIPXE.scriptUrl.host) }} +{{- $_ := set .Values.http.tinkServer "ip" (default $publicIP .Values.http.tinkServer.ip) }} +{{- $_ := set .Values.http.osieUrl "host" (default $publicIP .Values.http.osieUrl.host) }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: {{ .Values.name }} + name: {{ .Values.name }} + namespace: {{ .Release.Namespace | quote }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + app: {{ .Values.name }} + stack: tinkerbell + {{- with .Values.selector }} + {{- toYaml . | nindent 6 }} + {{- end }} + strategy: + type: {{ .Values.deployment.strategy.type }} + template: + metadata: + labels: + app: {{ .Values.name }} + stack: tinkerbell + {{- with .Values.selector }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + containers: + - image: {{ .Values.image }} + imagePullPolicy: {{ .Values.imagePullPolicy }} + args: + {{- range .Values.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: SMEE_LOG_LEVEL + value: {{ .Values.logLevel | quote }} + - name: SMEE_DHCP_ADDR + value: {{ printf "%v:%v" .Values.dhcp.ip .Values.dhcp.port | quote }} + - name: SMEE_DHCP_ENABLED + value: {{ .Values.dhcp.enabled | quote }} + - name: SMEE_DHCP_TFTP_PORT + value: {{ .Values.dhcp.tftpPort | quote }} + - name: SMEE_DHCP_HTTP_IPXE_BINARY_PATH + value: {{ .Values.dhcp.httpIPXE.binaryUrl.path | quote }} + - name: SMEE_DHCP_HTTP_IPXE_BINARY_PORT + value: {{ .Values.dhcp.httpIPXE.binaryUrl.port | quote }} + - name: SMEE_DHCP_HTTP_IPXE_BINARY_SCHEME + value: {{ .Values.dhcp.httpIPXE.binaryUrl.scheme | quote }} + - name: SMEE_DHCP_HTTP_IPXE_SCRIPT_PATH + value: {{ .Values.dhcp.httpIPXE.scriptUrl.path | quote }} + - name: SMEE_DHCP_HTTP_IPXE_SCRIPT_PORT + value: {{ .Values.dhcp.httpIPXE.scriptUrl.port | quote }} + - name: SMEE_DHCP_HTTP_IPXE_SCRIPT_SCHEME + value: {{ .Values.dhcp.httpIPXE.scriptUrl.scheme | quote }} + - name: SMEE_DHCP_MODE + value: {{ .Values.dhcp.mode | quote }} + - name: SMEE_EXTRA_KERNEL_ARGS + value: {{ join " " ( append .Values.http.additionalKernelArgs ( printf "tink_worker_image=%s" ( required "missing tinkWorkerImage" .Values.tinkWorkerImage ) ) ) | quote }} + - name: SMEE_HTTP_IPXE_BINARY_ENABLED + value: {{ .Values.http.ipxeBinaryEnabled | quote }} + - name: SMEE_HTTP_IPXE_SCRIPT_ENABLED + value: {{ .Values.http.ipxeScriptEnabled | quote }} + - name: SMEE_HTTP_PORT + value: {{ .Values.http.port | quote }} + - name: SMEE_OSIE_URL + value: {{include "urlJoiner" (dict "urlDict" .Values.http.osieUrl) | quote }} + - name: SMEE_TINK_SERVER + value: {{ printf "%v:%v" .Values.http.tinkServer.ip .Values.http.tinkServer.port | quote }} + - name: SMEE_TINK_SERVER_TLS + value: {{ .Values.http.tinkServer.tls | quote }} + - name: SMEE_TINK_SERVER_INSECURE_TLS + value: {{ .Values.http.tinkServer.insecureTLS | quote }} + - name: SMEE_TRUSTED_PROXIES + value: {{ required "missing trustedProxies" ( join "," $trustedProxies ) | quote }} + - name: SMEE_SYSLOG_ENABLED + value: {{ .Values.syslog.enabled | quote }} + - name: SMEE_IPXE_SCRIPT_PATCH + value: {{ .Values.ipxeScriptPatch | quote }} + - name: SMEE_TFTP_ENABLED + value: {{ .Values.tftp.enabled | quote }} + - name: SMEE_TFTP_TIMEOUT + value: {{ .Values.tftp.timeout | quote }} + - name: SMEE_TFTP_PORT + value: {{ .Values.tftp.port | quote }} + - name: SMEE_SYSLOG_PORT + value: {{ .Values.syslog.port | quote }} + - name: SMEE_HTTP_ADDR + value: {{ .Values.http.ip | quote }} + - name: SMEE_SYSLOG_ADDR + value: {{ .Values.syslog.ip | quote }} + - name: SMEE_TFTP_ADDR + value: {{ .Values.tftp.ip | quote }} + - name: SMEE_DHCP_HTTP_IPXE_BINARY_HOST + value: {{ .Values.dhcp.httpIPXE.binaryUrl.host | quote }} + - name: SMEE_DHCP_HTTP_IPXE_SCRIPT_HOST + value: {{ .Values.dhcp.httpIPXE.scriptUrl.host | quote }} + - name: SMEE_DHCP_SYSLOG_IP + value: {{ .Values.dhcp.syslogIp | quote }} + - name: SMEE_DHCP_TFTP_IP + value: {{ .Values.dhcp.tftpIp | quote }} + - name: SMEE_DHCP_IP_FOR_PACKET + value: {{ .Values.dhcp.ipForPacket | quote }} + - name: SMEE_ISO_ENABLED + value: {{ .Values.iso.enabled | quote }} + - name: SMEE_ISO_URL + value: {{ .Values.iso.url | quote }} + - name: SMEE_ISO_MAGIC_STRING + value: {{ .Values.iso.magicString | quote }} + - name: SMEE_ISO_STATIC_IPAM_ENABLED + value: {{ .Values.iso.staticIPAMEnabled | quote }} + {{- if eq $roleType "Role"}} + - name: SMEE_BACKEND_KUBE_NAMESPACE + value: {{ .Release.Namespace | quote }} + {{- end }} + {{- range .Values.additionalEnv }} + - name: {{ .name | quote }} + value: {{ .value | quote }} + {{- end }} + {{- if not .Values.hostNetwork }} + ports: + {{- include "smee.ports" ( merge ( dict "PortKey" "containerPort" ) .Values ) | indent 12 }} + {{- end }} + name: {{ .Values.name }} + resources: + limits: + cpu: {{ .Values.resources.limits.cpu }} + memory: {{ .Values.resources.limits.memory }} + requests: + cpu: {{ .Values.resources.requests.cpu }} + memory: {{ .Values.resources.requests.memory }} + {{- with .Values.additionalVolumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.additionalVolumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ .Values.name }} + {{- if .Values.hostNetwork }} + hostNetwork: true + {{- end }} + {{- with $nodeSelector }} + nodeSelector: + {{ toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.deployment.tolerations .Values.singleNodeClusterConfig.controlPlaneTolerationsEnabled }} + tolerations: + {{- .Values.deployment.tolerations | toYaml | nindent 8 }} + {{- if .Values.singleNodeClusterConfig.controlPlaneTolerationsEnabled }} + {{- include "singleNodeClusterConfig" . | indent 6 }} + {{- end }} + {{- end }} + {{- if .Values.deployment.affinity }} + affinity: + {{- .Values.deployment.affinity | toYaml | nindent 8 }} + {{- else if .Values.singleNodeClusterConfig.controlPlaneTolerationsEnabled }} + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + {{- include "preferWorkerNodes" (dict "nodeAffinityWeight" .Values.singleNodeClusterConfig.nodeAffinityWeight) | indent 10 }} + {{- end }} +{{- end }} diff --git a/packages/system/tinkerbell/charts/smee/templates/role-binding.yaml b/packages/system/tinkerbell/charts/smee/templates/role-binding.yaml new file mode 100644 index 000000000..84f6a1337 --- /dev/null +++ b/packages/system/tinkerbell/charts/smee/templates/role-binding.yaml @@ -0,0 +1,21 @@ +{{- if .Values.deploy }} +{{- $roleType := .Values.rbac.type }} +{{- if .Values.global }} +{{- $roleType = coalesce .Values.global.rbac.type .Values.rbac.type }} +{{- end }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: {{ printf "%sBinding" $roleType }} +metadata: + name: {{ .Values.rbac.bindingName }} + {{- if eq $roleType "Role" }} + namespace: {{ .Release.Namespace | quote }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: {{ $roleType }} + name: {{ .Values.rbac.name }} +subjects: + - kind: ServiceAccount + name: {{ .Values.name }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/packages/system/tinkerbell/charts/smee/templates/role.yaml b/packages/system/tinkerbell/charts/smee/templates/role.yaml new file mode 100644 index 000000000..600fc255e --- /dev/null +++ b/packages/system/tinkerbell/charts/smee/templates/role.yaml @@ -0,0 +1,17 @@ +{{- if .Values.deploy }} +{{- $roleType := .Values.rbac.type }} +{{- if .Values.global }} +{{- $roleType = coalesce .Values.global.rbac.type .Values.rbac.type }} +{{- end }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: {{ $roleType }} +metadata: + name: {{ .Values.rbac.name }} + {{- if eq $roleType "Role" }} + namespace: {{ .Release.Namespace | quote }} + {{- end }} +rules: + - apiGroups: ["tinkerbell.org"] + resources: ["hardware", "hardware/status"] + verbs: ["get", "list", "watch"] +{{- end }} diff --git a/packages/system/tinkerbell/charts/smee/templates/service-account.yaml b/packages/system/tinkerbell/charts/smee/templates/service-account.yaml new file mode 100644 index 000000000..252282f5d --- /dev/null +++ b/packages/system/tinkerbell/charts/smee/templates/service-account.yaml @@ -0,0 +1,7 @@ +{{- if .Values.deploy }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.name }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/packages/system/tinkerbell/charts/smee/templates/service.yaml b/packages/system/tinkerbell/charts/smee/templates/service.yaml new file mode 100644 index 000000000..ab7dd1145 --- /dev/null +++ b/packages/system/tinkerbell/charts/smee/templates/service.yaml @@ -0,0 +1,31 @@ +{{- if .Values.deploy }} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ .Values.name }} + name: {{ .Values.name }} + namespace: {{ .Release.Namespace | quote }} +spec: + type: ClusterIP + ports: + - name: tftp + port: 69 + targetPort: 69 + protocol: UDP + - name: http + port: {{ .Values.http.port }} + targetPort: {{ .Values.http.port }} + protocol: TCP + - name: syslog + port: {{ .Values.syslog.port }} + targetPort: {{ .Values.syslog.port }} + protocol: UDP + - name: dhcp + port: 67 + targetPort: 67 + protocol: UDP + selector: + app: {{ .Values.name }} +{{- end }} diff --git a/packages/system/tinkerbell/charts/smee/values.schema.json b/packages/system/tinkerbell/charts/smee/values.schema.json new file mode 100644 index 000000000..3d2cee525 --- /dev/null +++ b/packages/system/tinkerbell/charts/smee/values.schema.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "http": { + "type": "object", + "properties": { + "trustedProxies": { + "type": "array", + "items": { + "type": "string", + "description": "Specifies one or more IPv4/IPv6 addresses expressed using CIDR notation.", + "anyOf": [ + { + "pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$" + }, + { + "pattern": "^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$" + } + ] + } + } + } + }, + "rbac": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["Role", "ClusterRole"] + }, + "name": { + "type": "string" + }, + "bindingName": { + "type": "string" + } + } + } + } + } diff --git a/packages/system/tinkerbell/charts/smee/values.yaml b/packages/system/tinkerbell/charts/smee/values.yaml new file mode 100644 index 000000000..0bda77c90 --- /dev/null +++ b/packages/system/tinkerbell/charts/smee/values.yaml @@ -0,0 +1,166 @@ +# Toggle deployment of the service. +deploy: true + +# Name of the service used as the deployment name and label selectors. +name: smee + +# The image used to launch the container. +image: quay.io/tinkerbell/smee:v0.15.1 +imagePullPolicy: IfNotPresent + +# The number of pods to run. +replicas: 1 + +# Resources bounds applied to the container. +resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi + +deployment: + strategy: + type: RollingUpdate + tolerations: [] + affinity: {} + +# The log level for the container. +logLevel: "info" + +# The network mode to launch the smee container. When true, the smee container will use the +# host network. +hostNetwork: false + +# nodeSelector when defined will be constrain Pods to nodes with specific labels +nodeSelector: {} + +# publicIP when defined will be used as the IP in the following locations if they are not defined: +# dhcp.httpIPXE.binaryUrl.host, dhcp.httpIPXE.scriptUrl.host, tinkServer.ip, http.osieUrl.host, dhcp.ipForPacket, dhcp.tftpIp +# This is useful when all Tinkerbell services are running behind the same IP. +publicIP: "" + +# DHCP server configuration. Name is an identifier used across Kubernetes manifests for port +# identification, ip is the IP address to bind to, and port is the port to bind to. +dhcp: + enabled: true + name: smee-dhcp + mode: reservation + ip: 0.0.0.0 + port: 67 + ipForPacket: "" + tftpIp: "" + tftpPort: 69 + syslogIp: "" + httpIPXE: + binaryUrl: # http://:/ipxe + scheme: "http" + host: "" + port: 7171 + path: "/ipxe" + scriptUrl: # http://:/auto.ipxe + scheme: "http" + host: "" + port: 7171 + path: "/auto.ipxe" + + +# TFTP server configuration used to serve iPXE binaries. Name is an identifier used across +# Kubernetes manifests for port identification, ip is the IP address to bind to, and port is the +# port to bind to. +tftp: + enabled: true + name: smee-tftp + ip: 0.0.0.0 + port: 69 + timeout: 5s + +# HTTP server configuration used to serve iPXE scripts. Name is an identifier used across +# Kubernetes manifests for port identification, ip is the IP address to bind to, and port is the +# port to bind to. +http: + enabled: true + name: smee-http + ip: 0.0.0.0 + port: 7171 + # Tink Server configuration passed to the Tink Worker to establish a gRPC connection. + tinkServer: + ip: "" + port: 42113 + tls: false + insecureTLS: false + osieUrl: + scheme: "http" + host: "" + port: 8080 + path: "" + # Additional kernel arguments to pass to the OSIE. (k=v k=v) that are appended to the kernel cmdline in the iPXE script + additionalKernelArgs: [] + # enable iPXE HTTP binary server + ipxeBinaryEnabled: true + # enable iPXE HTTP script server + ipxeScriptEnabled: true + +# ISO settings +iso: + enabled: false + # the string pattern to match for in the source ISO, defaults to the one defined in HookOS + magicString: "" + # enable static IPAM for HookOS + staticIPAMEnabled: false + # an HTTP(S) URL target to an OSIE that is used for patching + url: "" + +# Trusted proxies defines a list of IP or CIDR ranges that are allowed to set the X-Forwarded-For + # header. This typically requires all Pod CIDRs in the cluster. + trustedProxies: [] + +# Syslog server configuration for the smee hosted syslog server. Name is an identifier used across +# Kubernetes manifests for port identification, ip is the IP address to bind to, and port is the +# port to bind to. +syslog: + enabled: true + name: smee-syslog + ip: 0.0.0.0 + port: 514 + +# The Tink Worker image passed to OSIE as a kernel arg for launching. +tinkWorkerImage: quay.io/tinkerbell/tink-worker:v0.12.1 + + +# Additional arguments to pass to the smee container. Some arguments are already defined - refer +# to the deployment.yaml template for details. +additionalArgs: [] + +# Additional environment variables to pass to the smee container. Each entry is expected to have a +# name and value key. Some keys are already defined - refer to the deployment.yaml template for +# details. +# +# Example +# - name: MY_ENV_VAR +# value: my-value +additionalEnv: [] + +# singleNodeClusterConfig to add tolerations for deployments on control plane nodes. This is defaulted to false. +singleNodeClusterConfig: + controlPlaneTolerationsEnabled: false + nodeAffinityWeight: 1 + +# Additional volumes on the output Deployment definition. +additionalVolumes: [ ] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the Smee container +additionalVolumeMounts: [ ] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +rbac: + type: Role # or ClusterRole + name: smee-role # or smee-cluster-role + bindingName: smee-rolebinding # or smee-cluster-rolebinding diff --git a/packages/system/tinkerbell/values.yaml b/packages/system/tinkerbell/values.yaml new file mode 100644 index 000000000..4b230f813 --- /dev/null +++ b/packages/system/tinkerbell/values.yaml @@ -0,0 +1,6 @@ +smee: + hostNetwork: true + trustedProxies: + - 0.0.0.0/0 + syslog: + enabled: false