diff --git a/.github/workflows/controller-bundle.yaml b/.github/workflows/controller-bundle.yaml deleted file mode 100644 index 1055661a4..000000000 --- a/.github/workflows/controller-bundle.yaml +++ /dev/null @@ -1,94 +0,0 @@ -name: Check Bundle - -on: - pull_request: - paths: - - 'controller/**' - -jobs: - check-bundle: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.24' - - - name: Cache bin directory (deploy/operator) - uses: actions/cache@v4 - with: - path: controller/deploy/operator/bin/ - key: ${{ runner.os }}-operator-bin-${{ hashFiles('controller/deploy/operator/go.mod') }} - restore-keys: | - ${{ runner.os }}-operator-bin- - - - name: Get version - run: | - if [ "${{ github.event_name }}" == "pull_request" ]; then - BASE_BRANCH="${{ github.base_ref }}" - if [ "$BASE_BRANCH" == "main" ]; then - TAG="latest" - elif [[ "$BASE_BRANCH" =~ ^release- ]]; then - TAG="$BASE_BRANCH" - else - echo "::error::Unknown base branch: $BASE_BRANCH" - exit 1 - fi - else - echo "::error::Unsupported event: ${{ github.event_name }}" - exit 1 - fi - echo "TAG=${TAG}" >> $GITHUB_ENV - echo "TAG=${TAG}" - - - name: Run make bundle - working-directory: controller/deploy/operator - run: | - make bundle IMG="quay.io/jumpstarter-dev/jumpstarter-operator:${TAG}" - - - name: Check for uncommitted changes - run: | - DIFF=$(git diff) - if [ -n "$DIFF" ]; then - # Filter out createdAt timestamp lines and context lines, check if any actual changes remain - FILTERED_DIFF=$(echo "$DIFF" | grep -vE '^(---|\+\+\+|@@|index|diff)' | grep -vE '^[+-].*createdAt:.*[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z' || true) - # Check if there are any non-timestamp, non-context changes - if [ -n "$FILTERED_DIFF" ] && [ -n "$(echo "$FILTERED_DIFF" | grep -E '^[+-]' || true)" ]; then - echo "::error::Uncommitted changes detected after running 'make bundle'. Please commit all bundle changes before pushing." - echo "::error::This can be done by running 'make bundle IMG=\"quay.io/jumpstarter-dev/jumpstarter-operator:${TAG}\"" - git diff - exit 1 - else - echo "Only timestamp changes detected (ignored). Bundle files are up to date." - # Reset the timestamp changes to keep the repo clean - git checkout -- . - fi - else - echo "No uncommitted changes detected. Bundle files are up to date." - fi - - - name: Ensure clean state before build-installer - run: | - # Reset any remaining changes from root - git checkout -- . || true - - - name: Run make build-installer - working-directory: controller/deploy/operator - run: | - make build-installer - - - name: Check for uncommitted changes after build-installer - run: | - if [ -n "$(git diff)" ]; then - echo "::error::Uncommitted changes detected after running 'make build-installer'. Please commit all installer changes before pushing." - echo "::error::This can be done by running 'make build-installer'" - git diff - exit 1 - else - echo "No uncommitted changes detected. Installer files are up to date." - fi diff --git a/controller/api/v1alpha1/client_types.go b/controller/api/v1alpha1/client_types.go index 73a3d6a01..8e2481b9a 100644 --- a/controller/api/v1alpha1/client_types.go +++ b/controller/api/v1alpha1/client_types.go @@ -41,6 +41,9 @@ type ClientStatus struct { // Client is the Schema for the identities API type Client struct { + // The Client in the Jumpstarter controller represents a user that can access the Jumpstarter Controller. + // Clients can be associated to external identity OIDC providers by providing Username, i.e. + // Spec.Username: "kc:user-name-in-keycloak" metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/controller/api/v1alpha1/exporter_types.go b/controller/api/v1alpha1/exporter_types.go index 9f17dd999..c7fd22ddb 100644 --- a/controller/api/v1alpha1/exporter_types.go +++ b/controller/api/v1alpha1/exporter_types.go @@ -52,6 +52,13 @@ const ( // Exporter is the Schema for the exporters API type Exporter struct { + // Exporters represent the services that connect to the physical or virtual + // devices. They are responsible for providing the access to the devices and + // for the communication with the devices. A jumpstarter exporter service + // should be run on a linux machine, or a pod, with the exporter credentials + // and the right configuration for this resource to become online. For + // more information see the Jumpstarter documentation: + // https://jumpstarter.dev/main/introduction/exporters.html#exporters metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/controller/api/v1alpha1/exporteraccesspolicy_types.go b/controller/api/v1alpha1/exporteraccesspolicy_types.go index 864a33c7a..43b0efc80 100644 --- a/controller/api/v1alpha1/exporteraccesspolicy_types.go +++ b/controller/api/v1alpha1/exporteraccesspolicy_types.go @@ -50,6 +50,8 @@ type ExporterAccessPolicyStatus struct { // ExporterAccessPolicy is the Schema for the exporteraccesspolicies API. type ExporterAccessPolicy struct { + // ExporterAccessPolicies are used to define the access policies for the exporters. + // they help organize, prioritize and restrict access to the exporters by clients. metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/controller/api/v1alpha1/lease_types.go b/controller/api/v1alpha1/lease_types.go index 97d4f5e6d..fdecd42a1 100644 --- a/controller/api/v1alpha1/lease_types.go +++ b/controller/api/v1alpha1/lease_types.go @@ -78,6 +78,14 @@ const ( // Lease is the Schema for the exporters API type Lease struct { + // Lease is the schema for the Leases API. Leases represent a + // request for a specific exporter by a client. The lease is + // acquired by the client and the exporter is assigned to the lease. + // The lease is released by the client when the client is done with + // the exporter. For more information see the Jumpstarter documentation: + // + // https://jumpstarter.dev/main/reference/man-pages/jmp.html#jmp-create-lease + // https://jumpstarter.dev/main/reference/man-pages/jmp.html#jmp-shell metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/controller/deploy/operator/Makefile b/controller/deploy/operator/Makefile index b87499dad..15f337e72 100644 --- a/controller/deploy/operator/Makefile +++ b/controller/deploy/operator/Makefile @@ -3,7 +3,19 @@ # To re-generate a bundle for another specific version without changing the standard setup, you can: # - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) # - use environment variables to overwrite this value (e.g export VERSION=0.0.2) -VERSION ?= 0.8.0 +VERSION ?= 0.8.1-rc.1 + +# REPLACES defines the previous operator version this release replaces in the OLM upgrade graph. +# Used to generate the release-config.yaml for FBC auto-release. +# Set to empty for the first release in a channel. +# See: https://redhat-openshift-ecosystem.github.io/operator-pipelines/users/fbc_autorelease/ +REPLACES ?= jumpstarter-operator.v0.8.0 + +# FBC_CHANNELS defines the FBC catalog channels for this release. +FBC_CHANNELS ?= alpha + +# OPENSHIFT_VERSIONS defines the Red Hat OpenShift version range injected into bundle metadata. +OPENSHIFT_VERSIONS ?= v4.18-v4.21 # CHANNELS define the bundle channels used in the bundle. # Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") @@ -305,7 +317,27 @@ bundle: manifests kustomize operator-sdk ## Generate bundle manifests and metada $(OPERATOR_SDK) generate kustomize manifests -q cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS) + @# Inject Red Hat OpenShift version range into bundle metadata (not handled by operator-sdk) + @if ! grep -q 'com.redhat.openshift.versions' bundle/metadata/annotations.yaml; then \ + echo ' com.redhat.openshift.versions: $(OPENSHIFT_VERSIONS)' >> bundle/metadata/annotations.yaml; \ + fi $(OPERATOR_SDK) bundle validate ./bundle + @# Generate release-config.yaml for FBC auto-release + @echo "---" > bundle/release-config.yaml + @echo "catalog_templates:" >> bundle/release-config.yaml + @echo " - template_name: basic.yaml" >> bundle/release-config.yaml + @echo " channels: [$(FBC_CHANNELS)]" >> bundle/release-config.yaml +ifneq ($(REPLACES),) + @echo " replaces: $(REPLACES)" >> bundle/release-config.yaml + @REPLACES_VER=$$(echo "$(REPLACES)" | sed 's/jumpstarter-operator\.v//'); \ + echo " skipRange: '>=$${REPLACES_VER} <$(VERSION)'" >> bundle/release-config.yaml +endif + @echo "Generated bundle/release-config.yaml" + +.PHONY: contribute +contribute: bundle ## Update community-operators repos with the current bundle. + cd contribute && \ + ./update-contributions.sh .PHONY: bundle-build bundle-build: ## Build the bundle image. diff --git a/controller/deploy/operator/bundle/manifests/jumpstarter-operator-controller-manager-metrics-service_v1_service.yaml b/controller/deploy/operator/bundle/manifests/jumpstarter-operator-controller-manager-metrics-service_v1_service.yaml deleted file mode 100644 index a6a7e3b84..000000000 --- a/controller/deploy/operator/bundle/manifests/jumpstarter-operator-controller-manager-metrics-service_v1_service.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - creationTimestamp: null - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - control-plane: controller-manager - name: jumpstarter-operator-controller-manager-metrics-service -spec: - ports: - - name: https - port: 8443 - protocol: TCP - targetPort: 8443 - selector: - app.kubernetes.io/name: jumpstarter-operator - control-plane: controller-manager -status: - loadBalancer: {} diff --git a/controller/deploy/operator/bundle/manifests/jumpstarter-operator-jumpstarter-admin-role_rbac.authorization.k8s.io_v1_clusterrole.yaml b/controller/deploy/operator/bundle/manifests/jumpstarter-operator-jumpstarter-admin-role_rbac.authorization.k8s.io_v1_clusterrole.yaml deleted file mode 100644 index c8e11263d..000000000 --- a/controller/deploy/operator/bundle/manifests/jumpstarter-operator-jumpstarter-admin-role_rbac.authorization.k8s.io_v1_clusterrole.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - creationTimestamp: null - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - name: jumpstarter-operator-jumpstarter-admin-role -rules: -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters - verbs: - - '*' -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters/status - verbs: - - get diff --git a/controller/deploy/operator/bundle/manifests/jumpstarter-operator-jumpstarter-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml b/controller/deploy/operator/bundle/manifests/jumpstarter-operator-jumpstarter-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml deleted file mode 100644 index 5bb9255f4..000000000 --- a/controller/deploy/operator/bundle/manifests/jumpstarter-operator-jumpstarter-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - creationTimestamp: null - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - name: jumpstarter-operator-jumpstarter-editor-role -rules: -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters/status - verbs: - - get diff --git a/controller/deploy/operator/bundle/manifests/jumpstarter-operator-jumpstarter-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml b/controller/deploy/operator/bundle/manifests/jumpstarter-operator-jumpstarter-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml deleted file mode 100644 index df3c96e65..000000000 --- a/controller/deploy/operator/bundle/manifests/jumpstarter-operator-jumpstarter-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - creationTimestamp: null - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - name: jumpstarter-operator-jumpstarter-viewer-role -rules: -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters - verbs: - - get - - list - - watch -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters/status - verbs: - - get diff --git a/controller/deploy/operator/bundle/manifests/jumpstarter-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml b/controller/deploy/operator/bundle/manifests/jumpstarter-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml deleted file mode 100644 index 262b65097..000000000 --- a/controller/deploy/operator/bundle/manifests/jumpstarter-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - creationTimestamp: null - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - name: jumpstarter-operator-metrics-reader -rules: -- nonResourceURLs: - - /metrics - verbs: - - get diff --git a/controller/deploy/operator/bundle/manifests/jumpstarter-operator.clusterserviceversion.yaml b/controller/deploy/operator/bundle/manifests/jumpstarter-operator.clusterserviceversion.yaml deleted file mode 100644 index f89707d45..000000000 --- a/controller/deploy/operator/bundle/manifests/jumpstarter-operator.clusterserviceversion.yaml +++ /dev/null @@ -1,431 +0,0 @@ -apiVersion: operators.coreos.com/v1alpha1 -kind: ClusterServiceVersion -metadata: - annotations: - alm-examples: |- - [ - { - "apiVersion": "operator.jumpstarter.dev/v1alpha1", - "kind": "Jumpstarter", - "metadata": { - "labels": { - "app.kubernetes.io/managed-by": "kustomize", - "app.kubernetes.io/name": "jumpstarter-operator" - }, - "name": "jumpstarter-sample" - }, - "spec": null - } - ] - capabilities: Basic Install - createdAt: "2026-02-03T14:19:23Z" - operators.operatorframework.io/builder: operator-sdk-v1.41.1 - operators.operatorframework.io/project_layout: go.kubebuilder.io/v4 - name: jumpstarter-operator.v0.8.0 - namespace: placeholder -spec: - apiservicedefinitions: {} - customresourcedefinitions: - owned: - - kind: Client - name: clients.jumpstarter.dev - version: v1alpha1 - - kind: ExporterAccessPolicy - name: exporteraccesspolicies.jumpstarter.dev - version: v1alpha1 - - kind: Exporter - name: exporters.jumpstarter.dev - version: v1alpha1 - - description: Jumpstarter is the Schema for the jumpstarters API. - displayName: Jumpstarter - kind: Jumpstarter - name: jumpstarters.operator.jumpstarter.dev - version: v1alpha1 - - kind: Lease - name: leases.jumpstarter.dev - version: v1alpha1 - description: Jumpstarter is a cloud-native framework for Hardware-in-the-Loop (HIL) - automation that bridges the gap between embedded development workflows and real-world - deployment environments. This operator installs and manages the Jumpstarter Controller, - which acts as the central brain for your testing infrastructure. It orchestrates - secure, shared access to physical hardware and virtual devices (represented as - "exporters") directly from your Kubernetes or OpenShift cluster. - displayName: Jumpstarter Operator - icon: - - base64data: "" - mediatype: "" - install: - spec: - clusterPermissions: - - rules: - - apiGroups: - - "" - resources: - - configmaps - - secrets - - serviceaccounts - - services - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - "" - resources: - - events - verbs: - - create - - patch - - apiGroups: - - "" - resources: - - services/status - verbs: - - get - - patch - - update - - apiGroups: - - apps - resources: - - deployments - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - apps - resources: - - deployments/status - verbs: - - get - - patch - - update - - apiGroups: - - cert-manager.io - resources: - - certificates - - issuers - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - cert-manager.io - resources: - - certificates/status - - clusterissuers/status - - issuers/status - verbs: - - get - - apiGroups: - - cert-manager.io - resources: - - clusterissuers - verbs: - - get - - list - - watch - - apiGroups: - - config.openshift.io - resources: - - ingresses - verbs: - - get - - list - - watch - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - jumpstarter.dev - resources: - - clients - - exporteraccesspolicies - - exporters - - leases - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - jumpstarter.dev - resources: - - clients/finalizers - - exporteraccesspolicies/finalizers - - exporters/finalizers - - leases/finalizers - verbs: - - update - - apiGroups: - - jumpstarter.dev - resources: - - clients/status - - exporteraccesspolicies/status - - exporters/status - - leases/status - verbs: - - get - - patch - - update - - apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - networking.k8s.io - resources: - - ingresses - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - networking.k8s.io - resources: - - ingresses/status - verbs: - - get - - patch - - update - - apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters/finalizers - verbs: - - update - - apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters/status - verbs: - - get - - patch - - update - - apiGroups: - - rbac.authorization.k8s.io - resources: - - rolebindings - - roles - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - route.openshift.io - resources: - - routes - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - route.openshift.io - resources: - - routes/custom-host - verbs: - - create - - get - - patch - - update - - apiGroups: - - route.openshift.io - resources: - - routes/status - verbs: - - get - - patch - - update - - apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create - - apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create - serviceAccountName: jumpstarter-operator-controller-manager - deployments: - - label: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - control-plane: controller-manager - name: jumpstarter-operator-controller-manager - spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: jumpstarter-operator - control-plane: controller-manager - strategy: {} - template: - metadata: - annotations: - kubectl.kubernetes.io/default-container: manager - labels: - app.kubernetes.io/name: jumpstarter-operator - control-plane: controller-manager - spec: - containers: - - args: - - --metrics-bind-address=:8443 - - --leader-elect - - --health-probe-bind-address=:8081 - command: - - /manager - image: quay.io/jumpstarter-dev/jumpstarter-operator:latest - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: /healthz - port: 8081 - initialDelaySeconds: 15 - periodSeconds: 20 - name: manager - readinessProbe: - httpGet: - path: /readyz - port: 8081 - initialDelaySeconds: 5 - periodSeconds: 10 - resources: - limits: - cpu: 500m - memory: 512Mi - requests: - cpu: 10m - memory: 256Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - securityContext: - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - serviceAccountName: jumpstarter-operator-controller-manager - terminationGracePeriodSeconds: 10 - permissions: - - 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 - serviceAccountName: jumpstarter-operator-controller-manager - strategy: deployment - installModes: - - supported: false - type: OwnNamespace - - supported: false - type: SingleNamespace - - supported: false - type: MultiNamespace - - supported: true - type: AllNamespaces - keywords: - - hil - - hardware-in-the-loop - - hardware - - device - - embedded - - testing - - framework - links: - - name: Jumpstarter Operator - url: https://jumpstarter.dev/main/getting-started/installation/service/index.html - maintainers: - - email: majopela@redhat.com - name: Miguel Angel Ajo - maturity: alpha - provider: - name: The Jumpstarter Community - url: https://jumpstarter.dev - version: 0.8.0 diff --git a/controller/deploy/operator/bundle/manifests/jumpstarter.dev_clients.yaml b/controller/deploy/operator/bundle/manifests/jumpstarter.dev_clients.yaml deleted file mode 100644 index 399fc3272..000000000 --- a/controller/deploy/operator/bundle/manifests/jumpstarter.dev_clients.yaml +++ /dev/null @@ -1,75 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.3 - creationTimestamp: null - name: clients.jumpstarter.dev -spec: - group: jumpstarter.dev - names: - kind: Client - listKind: ClientList - plural: clients - singular: client - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: Client is the Schema for the identities 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: ClientSpec defines the desired state of Identity - properties: - username: - type: string - type: object - status: - description: ClientStatus defines the observed state of Identity - properties: - credential: - description: Status field for the clients - properties: - 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 - type: object - x-kubernetes-map-type: atomic - endpoint: - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/controller/deploy/operator/bundle/manifests/jumpstarter.dev_exporteraccesspolicies.yaml b/controller/deploy/operator/bundle/manifests/jumpstarter.dev_exporteraccesspolicies.yaml deleted file mode 100644 index d4d27fb04..000000000 --- a/controller/deploy/operator/bundle/manifests/jumpstarter.dev_exporteraccesspolicies.yaml +++ /dev/null @@ -1,172 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.3 - creationTimestamp: null - name: exporteraccesspolicies.jumpstarter.dev -spec: - group: jumpstarter.dev - names: - kind: ExporterAccessPolicy - listKind: ExporterAccessPolicyList - plural: exporteraccesspolicies - singular: exporteraccesspolicy - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExporterAccessPolicy is the Schema for the exporteraccesspolicies - 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: ExporterAccessPolicySpec defines the desired state of ExporterAccessPolicy. - properties: - exporterSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - policies: - items: - properties: - from: - items: - properties: - clientSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - type: array - maximumDuration: - type: string - priority: - type: integer - spotAccess: - type: boolean - type: object - type: array - type: object - status: - description: ExporterAccessPolicyStatus defines the observed state of - ExporterAccessPolicy. - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/controller/deploy/operator/bundle/manifests/jumpstarter.dev_exporters.yaml b/controller/deploy/operator/bundle/manifests/jumpstarter.dev_exporters.yaml deleted file mode 100644 index c111bd68d..000000000 --- a/controller/deploy/operator/bundle/manifests/jumpstarter.dev_exporters.yaml +++ /dev/null @@ -1,166 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.3 - creationTimestamp: null - name: exporters.jumpstarter.dev -spec: - group: jumpstarter.dev - names: - kind: Exporter - listKind: ExporterList - plural: exporters - singular: exporter - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: Exporter is the Schema for the exporters 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: ExporterSpec defines the desired state of Exporter - properties: - username: - type: string - type: object - status: - description: ExporterStatus defines the observed state of Exporter - properties: - conditions: - description: Exporter status fields - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - credential: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - 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 - type: object - x-kubernetes-map-type: atomic - devices: - items: - properties: - labels: - additionalProperties: - type: string - type: object - parent_uuid: - type: string - uuid: - type: string - type: object - type: array - endpoint: - type: string - lastSeen: - format: date-time - type: string - leaseRef: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - 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 - type: object - x-kubernetes-map-type: atomic - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/controller/deploy/operator/bundle/manifests/jumpstarter.dev_leases.yaml b/controller/deploy/operator/bundle/manifests/jumpstarter.dev_leases.yaml deleted file mode 100644 index 2dfde9bbd..000000000 --- a/controller/deploy/operator/bundle/manifests/jumpstarter.dev_leases.yaml +++ /dev/null @@ -1,241 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.3 - creationTimestamp: null - name: leases.jumpstarter.dev -spec: - group: jumpstarter.dev - names: - kind: Lease - listKind: LeaseList - plural: leases - singular: lease - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.ended - name: Ended - type: boolean - - jsonPath: .spec.clientRef.name - name: Client - type: string - - jsonPath: .status.exporterRef.name - name: Exporter - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: Lease is the Schema for the exporters 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: LeaseSpec defines the desired state of Lease - properties: - beginTime: - description: |- - Requested start time. If omitted, lease starts when exporter is acquired. - Immutable after lease starts (cannot change the past). - format: date-time - type: string - clientRef: - description: The client that is requesting the lease - properties: - 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 - type: object - x-kubernetes-map-type: atomic - duration: - description: |- - Duration of the lease. Must be positive when provided. - Can be omitted (nil) when both BeginTime and EndTime are provided, - in which case it's calculated as EndTime - BeginTime. - type: string - endTime: - description: |- - Requested end time. If specified with BeginTime, Duration is calculated. - Can be updated to extend or shorten active leases. - format: date-time - type: string - release: - description: The release flag requests the controller to end the lease - now - type: boolean - selector: - description: The selector for the exporter to be used - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - required: - - clientRef - - selector - type: object - status: - description: LeaseStatus defines the observed state of Lease - properties: - beginTime: - description: |- - If the lease has been acquired an exporter name is assigned - and then it can be used, it will be empty while still pending - format: date-time - type: string - conditions: - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - endTime: - format: date-time - type: string - ended: - type: boolean - exporterRef: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - 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 - type: object - x-kubernetes-map-type: atomic - priority: - type: integer - spotAccess: - type: boolean - required: - - ended - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/controller/deploy/operator/bundle/manifests/operator.jumpstarter.dev_jumpstarters.yaml b/controller/deploy/operator/bundle/manifests/operator.jumpstarter.dev_jumpstarters.yaml deleted file mode 100644 index 72f5078ee..000000000 --- a/controller/deploy/operator/bundle/manifests/operator.jumpstarter.dev_jumpstarters.yaml +++ /dev/null @@ -1,1911 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - creationTimestamp: null - name: jumpstarters.operator.jumpstarter.dev -spec: - group: operator.jumpstarter.dev - names: - kind: Jumpstarter - listKind: JumpstarterList - plural: jumpstarters - singular: jumpstarter - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: Jumpstarter is the Schema for the jumpstarters 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: |- - JumpstarterSpec defines the desired state of a Jumpstarter deployment. A deployment - can be created in a namespace of the cluster, and that's where all the Jumpstarter - resources and services will reside. - properties: - authentication: - description: |- - Authentication configuration for client and exporter authentication. - Supports multiple authentication methods including internal tokens, Kubernetes tokens, and JWT. - properties: - autoProvisioning: - description: |- - Automatic user provisioning configuration, this is useful for creating - users authenticated by external identity providers in Jumpstarter. - properties: - enabled: - default: false - description: |- - Enable auto provisioning. - When disabled, users authenticated by external identity providers will - not be automatically created in Jumpstarter. - type: boolean - type: object - internal: - description: |- - Internal authentication configuration. - Built-in authenticator that issues tokens for clients and exporters. - This is the simplest authentication method and is enabled by default. - properties: - enabled: - default: true - description: |- - Enable the internal authentication method. - When disabled, clients cannot use internal tokens for authentication. - type: boolean - prefix: - default: 'internal:' - description: |- - Prefix to add to the subject claim of issued tokens. - Helps distinguish internal tokens from other authentication methods. - Example: "internal:" will result in subjects like "internal:user123" - maxLength: 50 - type: string - tokenLifetime: - default: 43800h - description: |- - Token validity duration for issued tokens. - After this duration, tokens expire and must be renewed. - type: string - type: object - jwt: - description: |- - JWT authentication configuration. - Enables authentication using external JWT tokens from OIDC providers. - Supports multiple JWT authenticators for different identity providers. - items: - description: JWTAuthenticator provides the configuration for - a single JWT authenticator. - properties: - claimMappings: - description: claimMappings points claims of a token to be - treated as user attributes. - properties: - extra: - description: |- - extra represents an option for the extra attribute. - expression must produce a string or string array value. - If the value is empty, the extra mapping will not be present. - - hard-coded extra key/value - - key: "foo" - valueExpression: "'bar'" - This will result in an extra attribute - foo: ["bar"] - - hard-coded key, value copying claim value - - key: "foo" - valueExpression: "claims.some_claim" - This will result in an extra attribute - foo: [value of some_claim] - - hard-coded key, value derived from claim value - - key: "admin" - valueExpression: '(has(claims.is_admin) && claims.is_admin) ? "true":""' - This will result in: - - if is_admin claim is present and true, extra attribute - admin: ["true"] - - if is_admin claim is present and false or is_admin claim is not present, no extra attribute will be added - items: - description: ExtraMapping provides the configuration - for a single extra mapping. - properties: - key: - description: |- - key is a string to use as the extra attribute key. - key must be a domain-prefix path (e.g. example.org/foo). All characters before the first "/" must be a valid - subdomain as defined by RFC 1123. All characters trailing the first "/" must - be valid HTTP Path characters as defined by RFC 3986. - key must be lowercase. - Required to be unique. - type: string - valueExpression: - description: |- - valueExpression is a CEL expression to extract extra attribute value. - valueExpression must produce a string or string array value. - "", [], and null values are treated as the extra mapping not being present. - Empty string values contained within a string array are filtered out. - - CEL expressions have access to the contents of the token claims, organized into CEL variable: - - 'claims' is a map of claim names to claim values. - For example, a variable named 'sub' can be accessed as 'claims.sub'. - Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'. - - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - type: string - required: - - key - - valueExpression - type: object - type: array - groups: - description: |- - groups represents an option for the groups attribute. - The claim's value must be a string or string array claim. - If groups.claim is set, the prefix must be specified (and can be the empty string). - If groups.expression is set, the expression must produce a string or string array value. - "", [], and null values are treated as the group mapping not being present. - properties: - claim: - description: |- - claim is the JWT claim to use. - Mutually exclusive with expression. - type: string - expression: - description: |- - expression represents the expression which will be evaluated by CEL. - - CEL expressions have access to the contents of the token claims, organized into CEL variable: - - 'claims' is a map of claim names to claim values. - For example, a variable named 'sub' can be accessed as 'claims.sub'. - Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'. - - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Mutually exclusive with claim and prefix. - type: string - prefix: - description: |- - prefix is prepended to claim's value to prevent clashes with existing names. - prefix needs to be set if claim is set and can be the empty string. - Mutually exclusive with expression. - type: string - type: object - uid: - description: |- - uid represents an option for the uid attribute. - Claim must be a singular string claim. - If uid.expression is set, the expression must produce a string value. - properties: - claim: - description: |- - claim is the JWT claim to use. - Either claim or expression must be set. - Mutually exclusive with expression. - type: string - expression: - description: |- - expression represents the expression which will be evaluated by CEL. - - CEL expressions have access to the contents of the token claims, organized into CEL variable: - - 'claims' is a map of claim names to claim values. - For example, a variable named 'sub' can be accessed as 'claims.sub'. - Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'. - - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Mutually exclusive with claim. - type: string - type: object - username: - description: |- - username represents an option for the username attribute. - The claim's value must be a singular string. - Same as the --oidc-username-claim and --oidc-username-prefix flags. - If username.expression is set, the expression must produce a string value. - If username.expression uses 'claims.email', then 'claims.email_verified' must be used in - username.expression or extra[*].valueExpression or claimValidationRules[*].expression. - An example claim validation rule expression that matches the validation automatically - applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true) == true'. By explicitly comparing - the value to true, we let type-checking see the result will be a boolean, and to make sure a non-boolean email_verified - claim will be caught at runtime. - - In the flag based approach, the --oidc-username-claim and --oidc-username-prefix are optional. If --oidc-username-claim is not set, - the default value is "sub". For the authentication config, there is no defaulting for claim or prefix. The claim and prefix must be set explicitly. - For claim, if --oidc-username-claim was not set with legacy flag approach, configure username.claim="sub" in the authentication config. - For prefix: - (1) --oidc-username-prefix="-", no prefix was added to the username. For the same behavior using authentication config, - set username.prefix="" - (2) --oidc-username-prefix="" and --oidc-username-claim != "email", prefix was "#". For the same - behavior using authentication config, set username.prefix="#" - (3) --oidc-username-prefix="". For the same behavior using authentication config, set username.prefix="" - properties: - claim: - description: |- - claim is the JWT claim to use. - Mutually exclusive with expression. - type: string - expression: - description: |- - expression represents the expression which will be evaluated by CEL. - - CEL expressions have access to the contents of the token claims, organized into CEL variable: - - 'claims' is a map of claim names to claim values. - For example, a variable named 'sub' can be accessed as 'claims.sub'. - Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'. - - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Mutually exclusive with claim and prefix. - type: string - prefix: - description: |- - prefix is prepended to claim's value to prevent clashes with existing names. - prefix needs to be set if claim is set and can be the empty string. - Mutually exclusive with expression. - type: string - type: object - required: - - username - type: object - claimValidationRules: - description: claimValidationRules are rules that are applied - to validate token claims to authenticate users. - items: - description: ClaimValidationRule provides the configuration - for a single claim validation rule. - properties: - claim: - description: |- - claim is the name of a required claim. - Same as --oidc-required-claim flag. - Only string claim keys are supported. - Mutually exclusive with expression and message. - type: string - expression: - description: |- - expression represents the expression which will be evaluated by CEL. - Must produce a boolean. - - CEL expressions have access to the contents of the token claims, organized into CEL variable: - - 'claims' is a map of claim names to claim values. - For example, a variable named 'sub' can be accessed as 'claims.sub'. - Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'. - Must return true for the validation to pass. - - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Mutually exclusive with claim and requiredValue. - type: string - message: - description: |- - message customizes the returned error message when expression returns false. - message is a literal string. - Mutually exclusive with claim and requiredValue. - type: string - requiredValue: - description: |- - requiredValue is the value of a required claim. - Same as --oidc-required-claim flag. - Only string claim values are supported. - If claim is set and requiredValue is not set, the claim must be present with a value set to the empty string. - Mutually exclusive with expression and message. - type: string - type: object - type: array - issuer: - description: issuer contains the basic OIDC provider connection - options. - properties: - audienceMatchPolicy: - description: |- - audienceMatchPolicy defines how the "audiences" field is used to match the "aud" claim in the presented JWT. - Allowed values are: - 1. "MatchAny" when multiple audiences are specified and - 2. empty (or unset) or "MatchAny" when a single audience is specified. - - - MatchAny: the "aud" claim in the presented JWT must match at least one of the entries in the "audiences" field. - For example, if "audiences" is ["foo", "bar"], the "aud" claim in the presented JWT must contain either "foo" or "bar" (and may contain both). - - - "": The match policy can be empty (or unset) when a single audience is specified in the "audiences" field. The "aud" claim in the presented JWT must contain the single audience (and may contain others). - - For more nuanced audience validation, use claimValidationRules. - example: claimValidationRule[].expression: 'sets.equivalent(claims.aud, ["bar", "foo", "baz"])' to require an exact match. - type: string - audiences: - description: |- - audiences is the set of acceptable audiences the JWT must be issued to. - At least one of the entries must match the "aud" claim in presented JWTs. - Same value as the --oidc-client-id flag (though this field supports an array). - Required to be non-empty. - items: - type: string - type: array - certificateAuthority: - description: |- - certificateAuthority contains PEM-encoded certificate authority certificates - used to validate the connection when fetching discovery information. - If unset, the system verifier is used. - Same value as the content of the file referenced by the --oidc-ca-file flag. - type: string - discoveryURL: - description: |- - discoveryURL, if specified, overrides the URL used to fetch discovery - information instead of using "{url}/.well-known/openid-configuration". - The exact value specified is used, so "/.well-known/openid-configuration" - must be included in discoveryURL if needed. - - The "issuer" field in the fetched discovery information must match the "issuer.url" field - in the AuthenticationConfiguration and will be used to validate the "iss" claim in the presented JWT. - This is for scenarios where the well-known and jwks endpoints are hosted at a different - location than the issuer (such as locally in the cluster). - - Example: - A discovery url that is exposed using kubernetes service 'oidc' in namespace 'oidc-namespace' - and discovery information is available at '/.well-known/openid-configuration'. - discoveryURL: "https://oidc.oidc-namespace/.well-known/openid-configuration" - certificateAuthority is used to verify the TLS connection and the hostname on the leaf certificate - must be set to 'oidc.oidc-namespace'. - - curl https://oidc.oidc-namespace/.well-known/openid-configuration (.discoveryURL field) - { - issuer: "https://oidc.example.com" (.url field) - } - - discoveryURL must be different from url. - Required to be unique across all JWT authenticators. - Note that egress selection configuration is not used for this network connection. - type: string - egressSelectorType: - description: |- - egressSelectorType is an indicator of which egress selection should be used for sending all traffic related - to this issuer (discovery, JWKS, distributed claims, etc). If unspecified, no custom dialer is used. - When specified, the valid choices are "controlplane" and "cluster". These correspond to the associated - values in the --egress-selector-config-file. - - - controlplane: for traffic intended to go to the control plane. - - - cluster: for traffic intended to go to the system being managed by Kubernetes. - type: string - url: - description: |- - url points to the issuer URL in a format https://url or https://url/path. - This must match the "iss" claim in the presented JWT, and the issuer returned from discovery. - Same value as the --oidc-issuer-url flag. - Discovery information is fetched from "{url}/.well-known/openid-configuration" unless overridden by discoveryURL. - Required to be unique across all JWT authenticators. - Note that egress selection configuration is not used for this network connection. - type: string - required: - - audiences - - url - type: object - userValidationRules: - description: |- - userValidationRules are rules that are applied to final user before completing authentication. - These allow invariants to be applied to incoming identities such as preventing the - use of the system: prefix that is commonly used by Kubernetes components. - The validation rules are logically ANDed together and must all return true for the validation to pass. - items: - description: UserValidationRule provides the configuration - for a single user info validation rule. - properties: - expression: - description: |- - expression represents the expression which will be evaluated by CEL. - Must return true for the validation to pass. - - CEL expressions have access to the contents of UserInfo, organized into CEL variable: - - 'user' - authentication.k8s.io/v1, Kind=UserInfo object - Refer to https://github.com/kubernetes/api/blob/release-1.28/authentication/v1/types.go#L105-L122 for the definition. - API documentation: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#userinfo-v1-authentication-k8s-io - - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - type: string - message: - description: |- - message customizes the returned error message when rule returns false. - message is a literal string. - type: string - required: - - expression - type: object - type: array - required: - - claimMappings - - issuer - type: object - type: array - k8s: - description: |- - Kubernetes authentication configuration. - Enables authentication using Kubernetes service account tokens. - Useful for integrating with existing Kubernetes RBAC policies. - properties: - enabled: - default: false - description: |- - Enable Kubernetes authentication. - When enabled, clients can authenticate using Kubernetes service account tokens. - type: boolean - type: object - type: object - baseDomain: - description: |- - Base domain used to construct FQDNs for all service endpoints. - This domain will be used to generate the default hostnames for Routes, Ingresses, and certificates. - Example: "example.com" will generate endpoints like "grpc.example.com", "router.example.com" - pattern: ^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$ - type: string - certManager: - description: |- - CertManager configuration for automatic TLS certificate management. - When enabled, jumpstarter will interact with cert-manager to automatically provision - and renew TLS certificates for all endpoints. Requires cert-manager to be installed in the cluster. - properties: - enabled: - default: false - description: |- - Enable cert-manager integration for automatic TLS certificate management. - When disabled, TLS certificates must be provided manually via secrets. - type: boolean - server: - description: |- - Server certificate configuration for controller and router endpoints. - Defines how server TLS certificates are issued. - properties: - issuerRef: - description: |- - Reference an existing cert-manager Issuer or ClusterIssuer. - Use this to integrate with existing PKI infrastructure (ACME, Vault, etc.). - This overrides SelfSigned.Enabled = true which is the default setting - properties: - caBundle: - description: |- - CABundle is an optional base64-encoded PEM CA certificate bundle for this issuer. - Required when using external issuers with non-publicly-trusted CAs. - This will be published to the {name}-service-ca-cert ConfigMap for clients to use. - For self-signed CA mode, this is automatically calculated from the CA secret. - format: byte - type: string - group: - default: cert-manager.io - description: |- - Group of the issuer resource. Defaults to cert-manager.io. - Only change this if using a custom issuer from a different API group. - type: string - kind: - default: Issuer - description: 'Kind of the issuer: "Issuer" for namespace-scoped - or "ClusterIssuer" for cluster-scoped.' - enum: - - Issuer - - ClusterIssuer - type: string - name: - description: Name of the Issuer or ClusterIssuer resource. - minLength: 1 - type: string - required: - - name - type: object - selfSigned: - description: |- - Create a self-signed CA managed by the operator. - The operator will create a self-signed Issuer and CA certificate, - then use that CA to issue server certificates. - properties: - caDuration: - default: 87600h - description: |- - Duration of the CA certificate validity. - The CA certificate is used to sign server certificates. - type: string - certDuration: - default: 8760h - description: |- - Duration of server certificate validity. - Server certificates are issued for controller and router endpoints. - type: string - enabled: - default: true - description: Enable self-signed CA mode. - type: boolean - renewBefore: - default: 360h - description: |- - Time before certificate expiration to trigger renewal. - Certificates will be renewed this duration before they expire. - type: string - type: object - type: object - type: object - controller: - default: {} - description: |- - Controller configuration for the main Jumpstarter API and gRPC services. - The controller handles gRPC and REST API requests from clients and exporters. - properties: - exporterOptions: - description: |- - Exporter options configuration. - Controls how exporters connect and behave when communicating with the controller. - properties: - offlineTimeout: - default: 180s - description: |- - Offline timeout duration for exporters. - After this duration without communication, an exporter is considered offline. - This drives the online/offline status field of exporters, and offline exporters - won't be considered for leases. - type: string - type: object - grpc: - description: |- - gRPC configuration for controller endpoints. - Defines how controller gRPC services are exposed and configured. - properties: - endpoints: - description: |- - List of gRPC endpoints to expose. - Each endpoint can use different networking methods (Route, Ingress, NodePort, or LoadBalancer) - based on your cluster setup. Example: Use Route for OpenShift, Ingress for standard Kubernetes. - items: - description: |- - Endpoint defines a single endpoint configuration. - An endpoint can use one or more networking methods: Route, Ingress, NodePort, or LoadBalancer. - Multiple methods can be configured simultaneously for the same address. - properties: - address: - description: |- - Address for this endpoint in the format "hostname", "hostname:port", "IPv4", "IPv4:port", "[IPv6]", or "[IPv6]:port". - Required for Route and Ingress endpoints. Optional for NodePort and LoadBalancer endpoints. - When optional, the address is used for certificate generation and DNS resolution. - Supports templating with $(replica) for replica-specific addresses. - Examples: "grpc.example.com", "grpc.example.com:9090", "192.168.1.1:8080", "[2001:db8::1]:8443", "router-$(replica).example.com" - pattern: ^(\[[0-9a-fA-F:\.]+\]|[0-9]+(\.[0-9]+){3}|[a-z0-9$]([a-z0-9\-\.\$\(\)]*[a-z0-9\)])?)(:[0-9]+)?$ - type: string - clusterIP: - description: |- - ClusterIP configuration for internal service access. - Creates a ClusterIP service for this endpoint. - Useful for internal service-to-service communication or when - using a different method to expose the service externally. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the ClusterIP service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the ClusterIP service for this endpoint. - When disabled, no ClusterIP service will be created for this endpoint. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the ClusterIP service. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - ingress: - description: |- - Ingress configuration for standard Kubernetes clusters. - Creates an Ingress resource for this endpoint. - Requires an ingress controller to be installed. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the Kubernetes Ingress resource. - Useful for configuring ingress-specific behavior, TLS settings, and load balancer options. - type: object - class: - default: default - description: |- - Ingress class name for the Kubernetes Ingress. - Specifies which ingress controller should handle this ingress. - type: string - enabled: - description: |- - Enable the Kubernetes Ingress for this endpoint. - When disabled, no Ingress resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the Kubernetes Ingress resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - loadBalancer: - description: |- - LoadBalancer configuration for cloud environments. - Creates a LoadBalancer service for this endpoint. - Requires cloud provider support for LoadBalancer services. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the LoadBalancer service. - Useful for configuring cloud provider-specific load balancer options. - Example: "service.beta.kubernetes.io/aws-load-balancer-type: nlb" - type: object - enabled: - description: |- - Enable the LoadBalancer service for this endpoint. - When disabled, no LoadBalancer service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the LoadBalancer service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - Port number for the LoadBalancer service. - Must be a valid port number (1-65535). - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - nodeport: - description: |- - NodePort configuration for direct node access. - Exposes the service on a specific port on each node. - Useful for bare-metal or simple cluster setups. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the NodePort service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the NodePort service for this endpoint. - When disabled, no NodePort service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the NodePort service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - NodePort port number to expose on each node. - Must be in the range 30000-32767 for most Kubernetes clusters. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - route: - description: |- - Route configuration for OpenShift clusters. - Creates an OpenShift Route resource for this endpoint. - Only applicable in OpenShift environments. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the OpenShift Route resource. - Useful for configuring route-specific behavior and TLS settings. - type: object - enabled: - description: |- - Enable the OpenShift Route for this endpoint. - When disabled, no Route resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the OpenShift Route resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - type: object - type: array - keepalive: - description: |- - Keepalive configuration for gRPC connections. - Controls connection health checks and idle connection management. - Helps maintain stable connections in load-balanced environments. - properties: - intervalTime: - default: 10s - description: |- - Interval between keepalive pings. - How often to send keepalive pings to check connection health. This is important - to keep TCP gRPC connections alive when traversing load balancers and proxies. - type: string - maxConnectionAge: - description: |- - Maximum age of a connection before it is closed and recreated. - Helps prevent issues with long-lived connections. It defaults to infinity. - type: string - maxConnectionAgeGrace: - description: |- - Grace period for closing connections that exceed MaxConnectionAge. - Allows ongoing RPCs to complete before closing the connection. - type: string - maxConnectionIdle: - description: |- - Maximum time a connection can remain idle before being closed. - It defaults to infinity. - type: string - minTime: - default: 1s - description: |- - Minimum time between keepalives that the connection will accept, under this threshold - the other side will get a GOAWAY signal. - Prevents excessive keepalive traffic on the network. - type: string - permitWithoutStream: - default: true - description: |- - Allow keepalive pings even when there are no active RPC streams. - Useful for detecting connection issues in idle connections. - This is important to keep TCP gRPC connections alive when traversing - load balancers and proxies. - type: boolean - timeout: - default: 180s - description: |- - Timeout for keepalive ping acknowledgment. - If a ping is not acknowledged within this time, the connection is considered broken. - The default is high to avoid issues when the network on a exporter is overloaded, i.e. - during flashing. - type: string - type: object - tls: - description: |- - TLS configuration for secure gRPC communication. - Requires a Kubernetes secret containing the TLS certificate and private key. - If spec.certManager.enabled is true, this secret will be automatically managed and - configured by cert-manager. - properties: - certSecret: - description: |- - Name of the Kubernetes secret containing the TLS certificate and private key. - The secret must contain 'tls.crt' and 'tls.key' keys. - If useCertManager is enabled, this secret will be automatically managed and - configured by cert-manager. - pattern: ^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$ - type: string - type: object - type: object - image: - default: quay.io/jumpstarter-dev/jumpstarter-controller:latest - description: |- - Container image for the controller pods in 'registry/repository/image:tag' format. - If not specified, defaults to the latest stable version of the Jumpstarter controller. - type: string - imagePullPolicy: - default: IfNotPresent - description: |- - Image pull policy for the controller container. - Controls when the container image should be pulled from the registry. - enum: - - Always - - IfNotPresent - - Never - type: string - login: - description: |- - Login endpoint configuration for simplified CLI login. - Provides authentication configuration discovery for the jmp login command. - The login service runs on HTTP and expects TLS to be terminated at the Route/Ingress level. - properties: - endpoints: - description: |- - List of login endpoints to expose. - Each endpoint can use different networking methods (Route, Ingress, NodePort, or LoadBalancer) - based on your cluster setup. - Note: Unlike gRPC endpoints, login endpoints use edge TLS termination (not passthrough). - items: - description: |- - Endpoint defines a single endpoint configuration. - An endpoint can use one or more networking methods: Route, Ingress, NodePort, or LoadBalancer. - Multiple methods can be configured simultaneously for the same address. - properties: - address: - description: |- - Address for this endpoint in the format "hostname", "hostname:port", "IPv4", "IPv4:port", "[IPv6]", or "[IPv6]:port". - Required for Route and Ingress endpoints. Optional for NodePort and LoadBalancer endpoints. - When optional, the address is used for certificate generation and DNS resolution. - Supports templating with $(replica) for replica-specific addresses. - Examples: "grpc.example.com", "grpc.example.com:9090", "192.168.1.1:8080", "[2001:db8::1]:8443", "router-$(replica).example.com" - pattern: ^(\[[0-9a-fA-F:\.]+\]|[0-9]+(\.[0-9]+){3}|[a-z0-9$]([a-z0-9\-\.\$\(\)]*[a-z0-9\)])?)(:[0-9]+)?$ - type: string - clusterIP: - description: |- - ClusterIP configuration for internal service access. - Creates a ClusterIP service for this endpoint. - Useful for internal service-to-service communication or when - using a different method to expose the service externally. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the ClusterIP service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the ClusterIP service for this endpoint. - When disabled, no ClusterIP service will be created for this endpoint. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the ClusterIP service. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - ingress: - description: |- - Ingress configuration for standard Kubernetes clusters. - Creates an Ingress resource for this endpoint. - Requires an ingress controller to be installed. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the Kubernetes Ingress resource. - Useful for configuring ingress-specific behavior, TLS settings, and load balancer options. - type: object - class: - default: default - description: |- - Ingress class name for the Kubernetes Ingress. - Specifies which ingress controller should handle this ingress. - type: string - enabled: - description: |- - Enable the Kubernetes Ingress for this endpoint. - When disabled, no Ingress resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the Kubernetes Ingress resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - loadBalancer: - description: |- - LoadBalancer configuration for cloud environments. - Creates a LoadBalancer service for this endpoint. - Requires cloud provider support for LoadBalancer services. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the LoadBalancer service. - Useful for configuring cloud provider-specific load balancer options. - Example: "service.beta.kubernetes.io/aws-load-balancer-type: nlb" - type: object - enabled: - description: |- - Enable the LoadBalancer service for this endpoint. - When disabled, no LoadBalancer service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the LoadBalancer service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - Port number for the LoadBalancer service. - Must be a valid port number (1-65535). - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - nodeport: - description: |- - NodePort configuration for direct node access. - Exposes the service on a specific port on each node. - Useful for bare-metal or simple cluster setups. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the NodePort service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the NodePort service for this endpoint. - When disabled, no NodePort service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the NodePort service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - NodePort port number to expose on each node. - Must be in the range 30000-32767 for most Kubernetes clusters. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - route: - description: |- - Route configuration for OpenShift clusters. - Creates an OpenShift Route resource for this endpoint. - Only applicable in OpenShift environments. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the OpenShift Route resource. - Useful for configuring route-specific behavior and TLS settings. - type: object - enabled: - description: |- - Enable the OpenShift Route for this endpoint. - When disabled, no Route resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the OpenShift Route resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - type: object - type: array - tls: - description: |- - TLS configuration for the login endpoint. - Specifies the Kubernetes secret containing the TLS certificate for edge termination. - If not specified and certManager is enabled, a default secret name will be generated. - properties: - secretName: - description: |- - Name of the Kubernetes secret containing the TLS certificate and private key. - The secret must contain 'tls.crt' and 'tls.key' keys. - Used for edge TLS termination at the Ingress/Route level. - pattern: ^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$ - type: string - type: object - type: object - replicas: - default: 2 - description: |- - Number of controller replicas to run. - Must be a positive integer. Minimum recommended value is 2 for high availability. - format: int32 - minimum: 1 - type: integer - resources: - description: |- - Resource requirements for controller pods. - Defines CPU and memory requests and limits for each controller pod. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This field depends on the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - 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: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - 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: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restApi: - description: |- - REST API configuration for HTTP-based clients. - Enables non-gRPC clients to interact with Jumpstarter for listing leases, - managing exporters, and creating new leases. Use this when you need HTTP/JSON access. - properties: - endpoints: - description: |- - List of REST API endpoints to expose. - Each endpoint can use different networking methods (Route, Ingress, NodePort, or LoadBalancer) - based on your cluster setup. - items: - description: |- - Endpoint defines a single endpoint configuration. - An endpoint can use one or more networking methods: Route, Ingress, NodePort, or LoadBalancer. - Multiple methods can be configured simultaneously for the same address. - properties: - address: - description: |- - Address for this endpoint in the format "hostname", "hostname:port", "IPv4", "IPv4:port", "[IPv6]", or "[IPv6]:port". - Required for Route and Ingress endpoints. Optional for NodePort and LoadBalancer endpoints. - When optional, the address is used for certificate generation and DNS resolution. - Supports templating with $(replica) for replica-specific addresses. - Examples: "grpc.example.com", "grpc.example.com:9090", "192.168.1.1:8080", "[2001:db8::1]:8443", "router-$(replica).example.com" - pattern: ^(\[[0-9a-fA-F:\.]+\]|[0-9]+(\.[0-9]+){3}|[a-z0-9$]([a-z0-9\-\.\$\(\)]*[a-z0-9\)])?)(:[0-9]+)?$ - type: string - clusterIP: - description: |- - ClusterIP configuration for internal service access. - Creates a ClusterIP service for this endpoint. - Useful for internal service-to-service communication or when - using a different method to expose the service externally. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the ClusterIP service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the ClusterIP service for this endpoint. - When disabled, no ClusterIP service will be created for this endpoint. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the ClusterIP service. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - ingress: - description: |- - Ingress configuration for standard Kubernetes clusters. - Creates an Ingress resource for this endpoint. - Requires an ingress controller to be installed. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the Kubernetes Ingress resource. - Useful for configuring ingress-specific behavior, TLS settings, and load balancer options. - type: object - class: - default: default - description: |- - Ingress class name for the Kubernetes Ingress. - Specifies which ingress controller should handle this ingress. - type: string - enabled: - description: |- - Enable the Kubernetes Ingress for this endpoint. - When disabled, no Ingress resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the Kubernetes Ingress resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - loadBalancer: - description: |- - LoadBalancer configuration for cloud environments. - Creates a LoadBalancer service for this endpoint. - Requires cloud provider support for LoadBalancer services. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the LoadBalancer service. - Useful for configuring cloud provider-specific load balancer options. - Example: "service.beta.kubernetes.io/aws-load-balancer-type: nlb" - type: object - enabled: - description: |- - Enable the LoadBalancer service for this endpoint. - When disabled, no LoadBalancer service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the LoadBalancer service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - Port number for the LoadBalancer service. - Must be a valid port number (1-65535). - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - nodeport: - description: |- - NodePort configuration for direct node access. - Exposes the service on a specific port on each node. - Useful for bare-metal or simple cluster setups. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the NodePort service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the NodePort service for this endpoint. - When disabled, no NodePort service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the NodePort service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - NodePort port number to expose on each node. - Must be in the range 30000-32767 for most Kubernetes clusters. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - route: - description: |- - Route configuration for OpenShift clusters. - Creates an OpenShift Route resource for this endpoint. - Only applicable in OpenShift environments. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the OpenShift Route resource. - Useful for configuring route-specific behavior and TLS settings. - type: object - enabled: - description: |- - Enable the OpenShift Route for this endpoint. - When disabled, no Route resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the OpenShift Route resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - type: object - type: array - tls: - description: |- - TLS configuration for secure HTTP communication. - Requires a Kubernetes secret containing the TLS certificate and private key. - properties: - certSecret: - description: |- - Name of the Kubernetes secret containing the TLS certificate and private key. - The secret must contain 'tls.crt' and 'tls.key' keys. - If useCertManager is enabled, this secret will be automatically managed and - configured by cert-manager. - pattern: ^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$ - type: string - type: object - type: object - type: object - routers: - default: {} - description: |- - Router configuration for the Jumpstarter router service. - Routers handle gRPC traffic routing and load balancing. - properties: - grpc: - description: |- - gRPC configuration for router endpoints. - Defines how router gRPC services are exposed and configured. - properties: - endpoints: - description: |- - List of gRPC endpoints to expose. - Each endpoint can use different networking methods (Route, Ingress, NodePort, or LoadBalancer) - based on your cluster setup. Example: Use Route for OpenShift, Ingress for standard Kubernetes. - items: - description: |- - Endpoint defines a single endpoint configuration. - An endpoint can use one or more networking methods: Route, Ingress, NodePort, or LoadBalancer. - Multiple methods can be configured simultaneously for the same address. - properties: - address: - description: |- - Address for this endpoint in the format "hostname", "hostname:port", "IPv4", "IPv4:port", "[IPv6]", or "[IPv6]:port". - Required for Route and Ingress endpoints. Optional for NodePort and LoadBalancer endpoints. - When optional, the address is used for certificate generation and DNS resolution. - Supports templating with $(replica) for replica-specific addresses. - Examples: "grpc.example.com", "grpc.example.com:9090", "192.168.1.1:8080", "[2001:db8::1]:8443", "router-$(replica).example.com" - pattern: ^(\[[0-9a-fA-F:\.]+\]|[0-9]+(\.[0-9]+){3}|[a-z0-9$]([a-z0-9\-\.\$\(\)]*[a-z0-9\)])?)(:[0-9]+)?$ - type: string - clusterIP: - description: |- - ClusterIP configuration for internal service access. - Creates a ClusterIP service for this endpoint. - Useful for internal service-to-service communication or when - using a different method to expose the service externally. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the ClusterIP service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the ClusterIP service for this endpoint. - When disabled, no ClusterIP service will be created for this endpoint. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the ClusterIP service. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - ingress: - description: |- - Ingress configuration for standard Kubernetes clusters. - Creates an Ingress resource for this endpoint. - Requires an ingress controller to be installed. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the Kubernetes Ingress resource. - Useful for configuring ingress-specific behavior, TLS settings, and load balancer options. - type: object - class: - default: default - description: |- - Ingress class name for the Kubernetes Ingress. - Specifies which ingress controller should handle this ingress. - type: string - enabled: - description: |- - Enable the Kubernetes Ingress for this endpoint. - When disabled, no Ingress resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the Kubernetes Ingress resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - loadBalancer: - description: |- - LoadBalancer configuration for cloud environments. - Creates a LoadBalancer service for this endpoint. - Requires cloud provider support for LoadBalancer services. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the LoadBalancer service. - Useful for configuring cloud provider-specific load balancer options. - Example: "service.beta.kubernetes.io/aws-load-balancer-type: nlb" - type: object - enabled: - description: |- - Enable the LoadBalancer service for this endpoint. - When disabled, no LoadBalancer service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the LoadBalancer service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - Port number for the LoadBalancer service. - Must be a valid port number (1-65535). - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - nodeport: - description: |- - NodePort configuration for direct node access. - Exposes the service on a specific port on each node. - Useful for bare-metal or simple cluster setups. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the NodePort service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the NodePort service for this endpoint. - When disabled, no NodePort service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the NodePort service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - NodePort port number to expose on each node. - Must be in the range 30000-32767 for most Kubernetes clusters. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - route: - description: |- - Route configuration for OpenShift clusters. - Creates an OpenShift Route resource for this endpoint. - Only applicable in OpenShift environments. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the OpenShift Route resource. - Useful for configuring route-specific behavior and TLS settings. - type: object - enabled: - description: |- - Enable the OpenShift Route for this endpoint. - When disabled, no Route resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the OpenShift Route resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - type: object - type: array - keepalive: - description: |- - Keepalive configuration for gRPC connections. - Controls connection health checks and idle connection management. - Helps maintain stable connections in load-balanced environments. - properties: - intervalTime: - default: 10s - description: |- - Interval between keepalive pings. - How often to send keepalive pings to check connection health. This is important - to keep TCP gRPC connections alive when traversing load balancers and proxies. - type: string - maxConnectionAge: - description: |- - Maximum age of a connection before it is closed and recreated. - Helps prevent issues with long-lived connections. It defaults to infinity. - type: string - maxConnectionAgeGrace: - description: |- - Grace period for closing connections that exceed MaxConnectionAge. - Allows ongoing RPCs to complete before closing the connection. - type: string - maxConnectionIdle: - description: |- - Maximum time a connection can remain idle before being closed. - It defaults to infinity. - type: string - minTime: - default: 1s - description: |- - Minimum time between keepalives that the connection will accept, under this threshold - the other side will get a GOAWAY signal. - Prevents excessive keepalive traffic on the network. - type: string - permitWithoutStream: - default: true - description: |- - Allow keepalive pings even when there are no active RPC streams. - Useful for detecting connection issues in idle connections. - This is important to keep TCP gRPC connections alive when traversing - load balancers and proxies. - type: boolean - timeout: - default: 180s - description: |- - Timeout for keepalive ping acknowledgment. - If a ping is not acknowledged within this time, the connection is considered broken. - The default is high to avoid issues when the network on a exporter is overloaded, i.e. - during flashing. - type: string - type: object - tls: - description: |- - TLS configuration for secure gRPC communication. - Requires a Kubernetes secret containing the TLS certificate and private key. - If spec.certManager.enabled is true, this secret will be automatically managed and - configured by cert-manager. - properties: - certSecret: - description: |- - Name of the Kubernetes secret containing the TLS certificate and private key. - The secret must contain 'tls.crt' and 'tls.key' keys. - If useCertManager is enabled, this secret will be automatically managed and - configured by cert-manager. - pattern: ^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$ - type: string - type: object - type: object - image: - default: quay.io/jumpstarter-dev/jumpstarter-controller:latest - description: |- - Container image for the router pods in 'registry/repository/image:tag' format. - If not specified, defaults to the latest stable version of the Jumpstarter router. - type: string - imagePullPolicy: - default: IfNotPresent - description: |- - Image pull policy for the router container. - Controls when the container image should be pulled from the registry. - enum: - - Always - - IfNotPresent - - Never - type: string - replicas: - default: 3 - description: |- - Number of router replicas to run. - Must be a positive integer. Minimum recommended value is 3 for high availability. - format: int32 - minimum: 1 - type: integer - resources: - description: |- - Resource requirements for router pods. - Defines CPU and memory requests and limits for each router pod. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This field depends on the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - 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: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - 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: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - topologySpreadConstraints: - description: |- - Topology spread constraints for router pod distribution. - Ensures router pods are distributed evenly across nodes and zones. - Useful for high availability and fault tolerance. - items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. - properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - format: int32 - type: integer - nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - If this value is nil, the behavior is equivalent to the Honor policy. - type: string - nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - If this value is nil, the behavior is equivalent to the Ignore policy. - type: string - topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - type: object - type: object - status: - description: |- - JumpstarterStatus defines the observed state of Jumpstarter. - Status information is reported through conditions following Kubernetes conventions. - properties: - conditions: - description: |- - Conditions represent the latest available observations of the Jumpstarter state. - Condition types include: - - CertManagerAvailable: cert-manager CRDs are installed in the cluster - - IssuerReady: The referenced or created issuer is ready to issue certificates - - ControllerCertificateReady: Controller TLS certificate is issued and secret exists - - RouterCertificatesReady: All router TLS certificates are issued and secrets exist - - ControllerDeploymentReady: Controller deployment is available - - RouterDeploymentsReady: All router deployments are available - - Ready: Overall system ready (aggregates all other conditions) - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/controller/deploy/operator/bundle/metadata/annotations.yaml b/controller/deploy/operator/bundle/metadata/annotations.yaml deleted file mode 100644 index bf1f6fb85..000000000 --- a/controller/deploy/operator/bundle/metadata/annotations.yaml +++ /dev/null @@ -1,14 +0,0 @@ -annotations: - # Core bundle annotations. - operators.operatorframework.io.bundle.mediatype.v1: registry+v1 - operators.operatorframework.io.bundle.manifests.v1: manifests/ - operators.operatorframework.io.bundle.metadata.v1: metadata/ - operators.operatorframework.io.bundle.package.v1: jumpstarter-operator - operators.operatorframework.io.bundle.channels.v1: alpha - operators.operatorframework.io.metrics.builder: operator-sdk-v1.41.1 - operators.operatorframework.io.metrics.mediatype.v1: metrics+v1 - operators.operatorframework.io.metrics.project_layout: go.kubebuilder.io/v4 - - # Annotations for testing. - operators.operatorframework.io.test.mediatype.v1: scorecard+v1 - operators.operatorframework.io.test.config.v1: tests/scorecard/ diff --git a/controller/deploy/operator/bundle/tests/scorecard/config.yaml b/controller/deploy/operator/bundle/tests/scorecard/config.yaml deleted file mode 100644 index 6ffe8227f..000000000 --- a/controller/deploy/operator/bundle/tests/scorecard/config.yaml +++ /dev/null @@ -1,70 +0,0 @@ -apiVersion: scorecard.operatorframework.io/v1alpha3 -kind: Configuration -metadata: - name: config -stages: -- parallel: true - tests: - - entrypoint: - - scorecard-test - - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.41.1 - labels: - suite: basic - test: basic-check-spec-test - storage: - spec: - mountPath: {} - - entrypoint: - - scorecard-test - - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.41.1 - labels: - suite: olm - test: olm-bundle-validation-test - storage: - spec: - mountPath: {} - - entrypoint: - - scorecard-test - - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.41.1 - labels: - suite: olm - test: olm-crds-have-validation-test - storage: - spec: - mountPath: {} - - entrypoint: - - scorecard-test - - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.41.1 - labels: - suite: olm - test: olm-crds-have-resources-test - storage: - spec: - mountPath: {} - - entrypoint: - - scorecard-test - - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.41.1 - labels: - suite: olm - test: olm-spec-descriptors-test - storage: - spec: - mountPath: {} - - entrypoint: - - scorecard-test - - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.41.1 - labels: - suite: olm - test: olm-status-descriptors-test - storage: - spec: - mountPath: {} -storage: - spec: - mountPath: {} diff --git a/controller/deploy/operator/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml b/controller/deploy/operator/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml index 8ac483465..d5fa1b039 100644 --- a/controller/deploy/operator/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml +++ b/controller/deploy/operator/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml @@ -14,15 +14,86 @@ metadata: "spec": { "baseDomain": "jumpstarter.example.com" } + }, + { + "apiVersion": "jumpstarter.dev/v1alpha1", + "kind": "Client", + "metadata": { + "name": "example-client" + }, + "spec": {} + }, + { + "apiVersion": "jumpstarter.dev/v1alpha1", + "kind": "Exporter", + "metadata": { + "name": "example-exporter" + }, + "spec": {} + }, + { + "apiVersion": "jumpstarter.dev/v1alpha1", + "kind": "Lease", + "metadata": { + "name": "example-lease" + }, + "spec": { + "clientRef": {"name": "example-client"}, + "selector": {} + } + }, + { + "apiVersion": "jumpstarter.dev/v1alpha1", + "kind": "ExporterAccessPolicy", + "metadata": { + "name": "example-policy" + }, + "spec": { + "exporterSelector": {}, + "policies": [{"from": [{"clientSelector": {}}]}] + } } ] capabilities: Basic Install + categories: Developer Tools, Integration & Delivery + com.redhat.openshift.versions: v4.18-v4.21 + containerImage: quay.io/jumpstarter-dev/jumpstarter-operator:latest + description: Jumpstarter is a cloud-native framework for Hardware-in-the-Loop + (HIL) testing and development + operators.operatorframework.io/internal-objects: '["clients.jumpstarter.dev","exporters.jumpstarter.dev","leases.jumpstarter.dev","exporteraccesspolicies.jumpstarter.dev"]' + repository: https://github.com/jumpstarter-dev/jumpstarter-controller + support: The Jumpstarter Community + labels: + operatorframework.io/arch.amd64: supported + operatorframework.io/arch.arm64: supported name: jumpstarter-operator.v0.0.0 namespace: placeholder spec: apiservicedefinitions: {} customresourcedefinitions: owned: + - description: Client represents a user identity for accessing the Jumpstarter + controller. + displayName: Client + kind: Client + name: clients.jumpstarter.dev + version: v1alpha1 + - description: Exporter represents a device exporter registered with the Jumpstarter + controller. + displayName: Exporter + kind: Exporter + name: exporters.jumpstarter.dev + version: v1alpha1 + - description: Lease represents a client's request to use an exporter. + displayName: Lease + kind: Lease + name: leases.jumpstarter.dev + version: v1alpha1 + - description: ExporterAccessPolicy defines access rules for exporters. + displayName: ExporterAccessPolicy + kind: ExporterAccessPolicy + name: exporteraccesspolicies.jumpstarter.dev + version: v1alpha1 - description: Jumpstarter is the Schema for the jumpstarters API. displayName: Jumpstarter kind: Jumpstarter @@ -36,8 +107,8 @@ spec: "exporters") directly from your Kubernetes or OpenShift cluster. displayName: Jumpstarter Operator icon: - - base64data: "" - mediatype: "" + - base64data: PHN2ZyB3aWR0aD0iMjkwIiBoZWlnaHQ9IjM2NCIgdmlld0JveD0iMCAwIDI5MCAzNjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik04Ny40OTIyIDIxMy42N0w4Ny41NCAyMTMuMjczQzg3Ljg4MTMgMjExLjU2NyA4Ny41NCAyMTAuMjAxIDg2LjUxNiAyMDkuMTc3Qzg1LjQ5MiAyMDcuODEyIDg0LjEyNjcgMjA3LjEyOSA4Mi40MiAyMDcuMTI5SDExLjc2NEMxMC4wNTczIDIwNy4xMjkgOC41MjEzMyAyMDcuODEyIDcuMTU2IDIwOS4xNzdDNi4xMzIgMjEwLjIwMSA1LjQ0OTMzIDIxMS41NjcgNS4xMDggMjEzLjI3M0wxLjUyNCAyNDMuNDgxQzAuODQxMzMzIDI1MS42NzMgMC41IDI1Ny40NzYgMC41IDI2MC44ODlDMC41IDI5MS45NTEgMTAuNzQgMzE2Ljg2OCAzMS4yMiAzMzUuNjQxQzUyLjA0MTMgMzU0LjA3MyA4MC4yMDEzIDM2My4yODkgMTE1LjcgMzYzLjI4OUMxNDAuOTU5IDM2My4yODkgMTYzLjk5OSAzNTguMzQgMTg0LjgyIDM0OC40NDFDMjA1Ljk4MyAzMzguMjAxIDIyMy4wNDkgMzI0LjAzNiAyMzYuMDIgMzA1Ljk0NUMyNDkuMzMyIDI4Ny44NTUgMjU3LjM1MyAyNjcuMDMzIDI2MC4wODQgMjQzLjQ4MUwyODkuMjY4IDYuOTM3MjZDMjg5LjYwOSA1LjIzMDYgMjg5LjI2OCAzLjg2NTI2IDI4OC4yNDQgMi44NDEyNUMyODcuMjIgMS40NzU5MiAyODUuODU1IDAuNzkzMjQ4IDI4NC4xNDggMC43OTMyNDhIMjE0LjAwNEMyMTIuMjk3IDAuNzkzMjQ4IDIxMC43NjEgMS40NzU5MiAyMDkuMzk2IDIuODQxMjVDMjA4LjM3MiAzLjg2NTI2IDIwNy42ODkgNS4yMzA2IDIwNy4zNDggNi45MzcyNkwxOTMuNzkyIDExNi41NzJIMjIwLjA5MkMyNDYuNTc2IDExNi41NzIgMjYxLjU5NiAxNDYuOTA2IDI0NS41NDMgMTY3Ljk2OUwxMTUuMTc1IDMzOS4wMkM5Ny4wNDc5IDM2Mi44MDQgNTkuMjYxNSAzNDUuNDIyIDY1LjUyNyAzMTYuMTgxTDg3LjQ5MjIgMjEzLjY3WiIgZmlsbD0iIzIxMjEyMSIvPgo8cGF0aCBkPSJNMTc2LjA3NyAxLjkyMjJMMzMuMDM4OCAxNjkuMTQ5QzI4LjU5ODYgMTc0LjM0IDMyLjI4NzMgMTgyLjM0OSAzOS4xMTgyIDE4Mi4zNDlIMTA4Ljg1MkMxMTMuOTQ1IDE4Mi4zNDkgMTE3Ljc0MiAxODcuMDQ1IDExNi42NzUgMTkyLjAyNUw4OC45OTQ0IDMyMS4yMDlDODguMDk5MyAzMjUuMzg2IDkzLjQ5NzMgMzI3Ljg3IDk2LjA4NjkgMzI0LjQ3MkwyMjYuNDU1IDE1My40MjFDMjMwLjQ2OCAxNDguMTU1IDIyNi43MTMgMTQwLjU3MiAyMjAuMDkyIDE0MC41NzJIMTUzLjg4QzE0OC41MzcgMTQwLjU3MiAxNDQuNjk2IDEzNS40MzUgMTQ2LjIwNyAxMzAuMzFMMTgyLjk1NCA1LjY1MzI3QzE4NC4xNzQgMS41MTUgMTc4Ljg4MiAtMS4zNTYzOCAxNzYuMDc3IDEuOTIyMloiIGZpbGw9IiNGRkMxMDciLz4KPC9zdmc+Cg== + mediatype: image/svg+xml install: spec: deployments: null @@ -65,7 +136,12 @@ spec: maintainers: - email: majopela@redhat.com name: Miguel Angel Ajo + - email: bzlotnik@redhat.com + name: Benny Zlotnik + - email: bkhizgiy@redhat.com + name: Bella Khizgiyaev maturity: alpha + minKubeVersion: 1.28.0 provider: name: The Jumpstarter Community url: https://jumpstarter.dev diff --git a/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_client.yaml b/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_client.yaml new file mode 100644 index 000000000..98e8e7d42 --- /dev/null +++ b/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_client.yaml @@ -0,0 +1,8 @@ +apiVersion: jumpstarter.dev/v1alpha1 +kind: Client +metadata: + name: client-sample + labels: + type: developer +spec: + username: "kc:user-name-in-keycloak" diff --git a/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_exporter.yaml b/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_exporter.yaml new file mode 100644 index 000000000..a20a52c5c --- /dev/null +++ b/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_exporter.yaml @@ -0,0 +1,7 @@ +apiVersion: jumpstarter.dev/v1alpha1 +kind: Exporter +metadata: + name: exporter-sample + labels: + type: nxp-imx8mm-evk +spec: {} diff --git a/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_exporteraccesspolicy.yaml b/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_exporteraccesspolicy.yaml new file mode 100644 index 000000000..d6afc8656 --- /dev/null +++ b/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_exporteraccesspolicy.yaml @@ -0,0 +1,13 @@ +apiVersion: jumpstarter.dev/v1alpha1 +kind: ExporterAccessPolicy +metadata: + name: exporteraccesspolicy-sample +spec: + exporterSelector: + matchLabels: + lab: jumpstarter + policies: + - from: + - clientSelector: + matchLabels: + team: platform diff --git a/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_lease.yaml b/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_lease.yaml new file mode 100644 index 000000000..7abc25fb3 --- /dev/null +++ b/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_lease.yaml @@ -0,0 +1,11 @@ +apiVersion: jumpstarter.dev/v1alpha1 +kind: Lease +metadata: + name: lease-sample +spec: + clientRef: + name: client-sample + selector: + matchLabels: + board: rcar-s4 + duration: "1h" diff --git a/controller/deploy/operator/config/samples/kustomization.yaml b/controller/deploy/operator/config/samples/kustomization.yaml index 3704fe7a6..335e9a002 100644 --- a/controller/deploy/operator/config/samples/kustomization.yaml +++ b/controller/deploy/operator/config/samples/kustomization.yaml @@ -1,4 +1,8 @@ ## Append samples of your project ## resources: - operator_v1alpha1_jumpstarter.yaml +- jumpstarter_v1alpha1_client.yaml +- jumpstarter_v1alpha1_exporter.yaml +- jumpstarter_v1alpha1_lease.yaml +- jumpstarter_v1alpha1_exporteraccesspolicy.yaml # +kubebuilder:scaffold:manifestskustomizesamples diff --git a/controller/deploy/operator/contribute/.gitignore b/controller/deploy/operator/contribute/.gitignore new file mode 100644 index 000000000..48fd1df49 --- /dev/null +++ b/controller/deploy/operator/contribute/.gitignore @@ -0,0 +1,2 @@ +community-operators/* +community-operators-prod/* diff --git a/controller/deploy/operator/contribute/update-contributions.sh b/controller/deploy/operator/contribute/update-contributions.sh new file mode 100755 index 000000000..4c5ab49e9 --- /dev/null +++ b/controller/deploy/operator/contribute/update-contributions.sh @@ -0,0 +1,135 @@ +#!/bin/bash +set -euo pipefail + +# Target repos: "clone-url local-directory" +# Add or remove entries here to sync to more/fewer upstreams. + +GITHUB_USER=${GITHUB_USER:-"mangelajo"} + +COMMUNITY_OPS=( + "git@github.com:k8s-operatorhub/community-operators.git community-operators" + "git@github.com:redhat-openshift-ecosystem/community-operators-prod.git community-operators-prod" +) + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +OPERATOR_DIR="${SCRIPT_DIR}/.." +BUNDLE_DIR="${OPERATOR_DIR}/bundle" +CSV_PATH="${BUNDLE_DIR}/manifests/jumpstarter-operator.clusterserviceversion.yaml" +RELEASE_CONFIG_PATH="${BUNDLE_DIR}/release-config.yaml" + +if [ ! -f "$CSV_PATH" ]; then + echo "Error: CSV not found at $CSV_PATH" + echo "Run 'make bundle' or 'make contribute' from the operator directory first." >&2 + exit 1 +fi + +VERSION=$(grep "^ version:" "$CSV_PATH" | awk '{print $2}') +if [ -z "$VERSION" ]; then + echo "Error: failed to extract VERSION from $CSV_PATH" >&2 + echo "Expected a line matching '^ version:' in $CSV_PATH but got nothing." >&2 + exit 1 +fi + +# Validate release-config.yaml for FBC auto-release +# See: https://redhat-openshift-ecosystem.github.io/operator-pipelines/users/fbc_autorelease/ +if [ ! -f "$RELEASE_CONFIG_PATH" ]; then + echo "Error: release-config.yaml not found at $RELEASE_CONFIG_PATH" >&2 + echo "" >&2 + echo "The FBC auto-release pipeline requires a release-config.yaml in the bundle directory." >&2 + echo "Set REPLACES in the Makefile and re-run 'make bundle', or create it manually:" >&2 + echo "" >&2 + echo " cat > ${RELEASE_CONFIG_PATH} <&2 + echo " ---" >&2 + echo " catalog_templates:" >&2 + echo " - template_name: basic.yaml" >&2 + echo " channels: [alpha]" >&2 + echo " replaces: jumpstarter-operator.vX.Y.Z" >&2 + echo " skipRange: '>=X.Y.Z <${VERSION}'" >&2 + echo " EOF" >&2 + echo "" >&2 + echo "Then re-run 'make contribute'." >&2 + exit 1 +fi + +REPLACES=$(grep "replaces:" "$RELEASE_CONFIG_PATH" | awk '{print $2}' | head -1) +CHANNELS=$(grep "channels:" "$RELEASE_CONFIG_PATH" | sed 's/.*channels: *\[//;s/\].*//' | head -1) +SKIP_RANGE=$(grep "skipRange:" "$RELEASE_CONFIG_PATH" | sed "s/.*skipRange: *['\"]//;s/['\"]$//" | head -1) + +# Extract the version from the replaces field (strip "jumpstarter-operator.v" prefix) +if [ -n "$REPLACES" ]; then + REPLACES_VERSION="${REPLACES#jumpstarter-operator.v}" + if [ "$REPLACES_VERSION" = "$VERSION" ]; then + echo "Error: 'replaces' version ($REPLACES_VERSION) is the same as the bundle version ($VERSION)." >&2 + echo "Update REPLACES in the Makefile to point to the previous release." >&2 + exit 1 + fi +fi + +echo "" +echo "============================================" +echo " Bundle version : ${VERSION}" +echo " Channels : ${CHANNELS:-"(not set)"}" +echo " Replaces : ${REPLACES:-"(not set)"}" +echo " Skip range : ${SKIP_RANGE:-"(not set)"}" +echo "============================================" +echo "" +read -r -p "Proceed with contribution? [y/N] " confirm +if [[ ! "$confirm" =~ ^[Yy]$ ]]; then + echo "" + echo "Aborted. To update these values, edit:" + echo " - VERSION / REPLACES in: ${OPERATOR_DIR}/Makefile" + echo " - Or directly: ${RELEASE_CONFIG_PATH}" + echo "Then re-run 'make bundle' followed by 'make contribute'." + exit 1 +fi + +# Clone any missing repos and ensure "user" remote points to the GITHUB_USER fork +for entry in "${COMMUNITY_OPS[@]}"; do + read -r url dir <<< "$entry" + # Derive the repo name (e.g. "community-operators") from the clone URL + repo_name="$(basename "$url" .git)" + user_fork="git@github.com:${GITHUB_USER}/${repo_name}.git" + + if [ ! -d "$dir" ]; then + echo "Cloning $url into $dir ..." + git clone "$url" "$dir" + else + echo "Using existing directory: $dir" + fi + + # Add or update the "user" remote for the fork + ( + cd "$dir" || exit 1 + if git remote get-url user &>/dev/null; then + git remote set-url user "$user_fork" + else + git remote add user "$user_fork" + fi + echo " user remote -> $user_fork" + ) +done + +# Create/reset release branch from main in each repo +BRANCH="jumpstarter-operator-release-${VERSION}" +for entry in "${COMMUNITY_OPS[@]}"; do + read -r url dir <<< "$entry" + echo "--- $dir: switching to branch $BRANCH ---" + (cd "$dir" || exit 1; git fetch --all && git checkout remotes/origin/main -B "$BRANCH") +done + +# Copy bundle into each repo and commit +for entry in "${COMMUNITY_OPS[@]}"; do + read -r url dir <<< "$entry" + dest="${dir}/operators/jumpstarter-operator/${VERSION}" + echo "Updating ${dir} to version ${VERSION}" + mkdir -p "$dest" + cp -v -r -f "${BUNDLE_DIR}"/* "$dest" + (cd "$dir" || exit 1; git add "operators/jumpstarter-operator/${VERSION}" && git commit -s -m "operator jumpstarter-operator (${VERSION})") +done + +echo "" +echo "Done. You can review the commits and push to your fork:" +for entry in "${COMMUNITY_OPS[@]}"; do + read -r url dir <<< "$entry" + echo " cd contribute/$dir && git push -f user ${BRANCH}" +done diff --git a/controller/deploy/operator/dist/install.yaml b/controller/deploy/operator/dist/install.yaml deleted file mode 100644 index 4f123e283..000000000 --- a/controller/deploy/operator/dist/install.yaml +++ /dev/null @@ -1,3067 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - control-plane: controller-manager - name: jumpstarter-operator-system ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.3 - name: clients.jumpstarter.dev -spec: - group: jumpstarter.dev - names: - kind: Client - listKind: ClientList - plural: clients - singular: client - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: Client is the Schema for the identities 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: ClientSpec defines the desired state of Identity - properties: - username: - type: string - type: object - status: - description: ClientStatus defines the observed state of Identity - properties: - credential: - description: Status field for the clients - properties: - 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 - type: object - x-kubernetes-map-type: atomic - endpoint: - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.3 - name: exporteraccesspolicies.jumpstarter.dev -spec: - group: jumpstarter.dev - names: - kind: ExporterAccessPolicy - listKind: ExporterAccessPolicyList - plural: exporteraccesspolicies - singular: exporteraccesspolicy - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: ExporterAccessPolicy is the Schema for the exporteraccesspolicies - 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: ExporterAccessPolicySpec defines the desired state of ExporterAccessPolicy. - properties: - exporterSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - policies: - items: - properties: - from: - items: - properties: - clientSelector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - type: array - maximumDuration: - type: string - priority: - type: integer - spotAccess: - type: boolean - type: object - type: array - type: object - status: - description: ExporterAccessPolicyStatus defines the observed state of - ExporterAccessPolicy. - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.3 - name: exporters.jumpstarter.dev -spec: - group: jumpstarter.dev - names: - kind: Exporter - listKind: ExporterList - plural: exporters - singular: exporter - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: Exporter is the Schema for the exporters 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: ExporterSpec defines the desired state of Exporter - properties: - username: - type: string - type: object - status: - description: ExporterStatus defines the observed state of Exporter - properties: - conditions: - description: Exporter status fields - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - credential: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - 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 - type: object - x-kubernetes-map-type: atomic - devices: - items: - properties: - labels: - additionalProperties: - type: string - type: object - parent_uuid: - type: string - uuid: - type: string - type: object - type: array - endpoint: - type: string - lastSeen: - format: date-time - type: string - leaseRef: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - 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 - type: object - x-kubernetes-map-type: atomic - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.18.0 - name: jumpstarters.operator.jumpstarter.dev -spec: - group: operator.jumpstarter.dev - names: - kind: Jumpstarter - listKind: JumpstarterList - plural: jumpstarters - singular: jumpstarter - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: Jumpstarter is the Schema for the jumpstarters 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: |- - JumpstarterSpec defines the desired state of a Jumpstarter deployment. A deployment - can be created in a namespace of the cluster, and that's where all the Jumpstarter - resources and services will reside. - properties: - authentication: - description: |- - Authentication configuration for client and exporter authentication. - Supports multiple authentication methods including internal tokens, Kubernetes tokens, and JWT. - properties: - autoProvisioning: - description: |- - Automatic user provisioning configuration, this is useful for creating - users authenticated by external identity providers in Jumpstarter. - properties: - enabled: - default: false - description: |- - Enable auto provisioning. - When disabled, users authenticated by external identity providers will - not be automatically created in Jumpstarter. - type: boolean - type: object - internal: - description: |- - Internal authentication configuration. - Built-in authenticator that issues tokens for clients and exporters. - This is the simplest authentication method and is enabled by default. - properties: - enabled: - default: true - description: |- - Enable the internal authentication method. - When disabled, clients cannot use internal tokens for authentication. - type: boolean - prefix: - default: 'internal:' - description: |- - Prefix to add to the subject claim of issued tokens. - Helps distinguish internal tokens from other authentication methods. - Example: "internal:" will result in subjects like "internal:user123" - maxLength: 50 - type: string - tokenLifetime: - default: 43800h - description: |- - Token validity duration for issued tokens. - After this duration, tokens expire and must be renewed. - type: string - type: object - jwt: - description: |- - JWT authentication configuration. - Enables authentication using external JWT tokens from OIDC providers. - Supports multiple JWT authenticators for different identity providers. - items: - description: JWTAuthenticator provides the configuration for - a single JWT authenticator. - properties: - claimMappings: - description: claimMappings points claims of a token to be - treated as user attributes. - properties: - extra: - description: |- - extra represents an option for the extra attribute. - expression must produce a string or string array value. - If the value is empty, the extra mapping will not be present. - - hard-coded extra key/value - - key: "foo" - valueExpression: "'bar'" - This will result in an extra attribute - foo: ["bar"] - - hard-coded key, value copying claim value - - key: "foo" - valueExpression: "claims.some_claim" - This will result in an extra attribute - foo: [value of some_claim] - - hard-coded key, value derived from claim value - - key: "admin" - valueExpression: '(has(claims.is_admin) && claims.is_admin) ? "true":""' - This will result in: - - if is_admin claim is present and true, extra attribute - admin: ["true"] - - if is_admin claim is present and false or is_admin claim is not present, no extra attribute will be added - items: - description: ExtraMapping provides the configuration - for a single extra mapping. - properties: - key: - description: |- - key is a string to use as the extra attribute key. - key must be a domain-prefix path (e.g. example.org/foo). All characters before the first "/" must be a valid - subdomain as defined by RFC 1123. All characters trailing the first "/" must - be valid HTTP Path characters as defined by RFC 3986. - key must be lowercase. - Required to be unique. - type: string - valueExpression: - description: |- - valueExpression is a CEL expression to extract extra attribute value. - valueExpression must produce a string or string array value. - "", [], and null values are treated as the extra mapping not being present. - Empty string values contained within a string array are filtered out. - - CEL expressions have access to the contents of the token claims, organized into CEL variable: - - 'claims' is a map of claim names to claim values. - For example, a variable named 'sub' can be accessed as 'claims.sub'. - Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'. - - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - type: string - required: - - key - - valueExpression - type: object - type: array - groups: - description: |- - groups represents an option for the groups attribute. - The claim's value must be a string or string array claim. - If groups.claim is set, the prefix must be specified (and can be the empty string). - If groups.expression is set, the expression must produce a string or string array value. - "", [], and null values are treated as the group mapping not being present. - properties: - claim: - description: |- - claim is the JWT claim to use. - Mutually exclusive with expression. - type: string - expression: - description: |- - expression represents the expression which will be evaluated by CEL. - - CEL expressions have access to the contents of the token claims, organized into CEL variable: - - 'claims' is a map of claim names to claim values. - For example, a variable named 'sub' can be accessed as 'claims.sub'. - Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'. - - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Mutually exclusive with claim and prefix. - type: string - prefix: - description: |- - prefix is prepended to claim's value to prevent clashes with existing names. - prefix needs to be set if claim is set and can be the empty string. - Mutually exclusive with expression. - type: string - type: object - uid: - description: |- - uid represents an option for the uid attribute. - Claim must be a singular string claim. - If uid.expression is set, the expression must produce a string value. - properties: - claim: - description: |- - claim is the JWT claim to use. - Either claim or expression must be set. - Mutually exclusive with expression. - type: string - expression: - description: |- - expression represents the expression which will be evaluated by CEL. - - CEL expressions have access to the contents of the token claims, organized into CEL variable: - - 'claims' is a map of claim names to claim values. - For example, a variable named 'sub' can be accessed as 'claims.sub'. - Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'. - - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Mutually exclusive with claim. - type: string - type: object - username: - description: |- - username represents an option for the username attribute. - The claim's value must be a singular string. - Same as the --oidc-username-claim and --oidc-username-prefix flags. - If username.expression is set, the expression must produce a string value. - If username.expression uses 'claims.email', then 'claims.email_verified' must be used in - username.expression or extra[*].valueExpression or claimValidationRules[*].expression. - An example claim validation rule expression that matches the validation automatically - applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true) == true'. By explicitly comparing - the value to true, we let type-checking see the result will be a boolean, and to make sure a non-boolean email_verified - claim will be caught at runtime. - - In the flag based approach, the --oidc-username-claim and --oidc-username-prefix are optional. If --oidc-username-claim is not set, - the default value is "sub". For the authentication config, there is no defaulting for claim or prefix. The claim and prefix must be set explicitly. - For claim, if --oidc-username-claim was not set with legacy flag approach, configure username.claim="sub" in the authentication config. - For prefix: - (1) --oidc-username-prefix="-", no prefix was added to the username. For the same behavior using authentication config, - set username.prefix="" - (2) --oidc-username-prefix="" and --oidc-username-claim != "email", prefix was "#". For the same - behavior using authentication config, set username.prefix="#" - (3) --oidc-username-prefix="". For the same behavior using authentication config, set username.prefix="" - properties: - claim: - description: |- - claim is the JWT claim to use. - Mutually exclusive with expression. - type: string - expression: - description: |- - expression represents the expression which will be evaluated by CEL. - - CEL expressions have access to the contents of the token claims, organized into CEL variable: - - 'claims' is a map of claim names to claim values. - For example, a variable named 'sub' can be accessed as 'claims.sub'. - Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'. - - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Mutually exclusive with claim and prefix. - type: string - prefix: - description: |- - prefix is prepended to claim's value to prevent clashes with existing names. - prefix needs to be set if claim is set and can be the empty string. - Mutually exclusive with expression. - type: string - type: object - required: - - username - type: object - claimValidationRules: - description: claimValidationRules are rules that are applied - to validate token claims to authenticate users. - items: - description: ClaimValidationRule provides the configuration - for a single claim validation rule. - properties: - claim: - description: |- - claim is the name of a required claim. - Same as --oidc-required-claim flag. - Only string claim keys are supported. - Mutually exclusive with expression and message. - type: string - expression: - description: |- - expression represents the expression which will be evaluated by CEL. - Must produce a boolean. - - CEL expressions have access to the contents of the token claims, organized into CEL variable: - - 'claims' is a map of claim names to claim values. - For example, a variable named 'sub' can be accessed as 'claims.sub'. - Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'. - Must return true for the validation to pass. - - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - - Mutually exclusive with claim and requiredValue. - type: string - message: - description: |- - message customizes the returned error message when expression returns false. - message is a literal string. - Mutually exclusive with claim and requiredValue. - type: string - requiredValue: - description: |- - requiredValue is the value of a required claim. - Same as --oidc-required-claim flag. - Only string claim values are supported. - If claim is set and requiredValue is not set, the claim must be present with a value set to the empty string. - Mutually exclusive with expression and message. - type: string - type: object - type: array - issuer: - description: issuer contains the basic OIDC provider connection - options. - properties: - audienceMatchPolicy: - description: |- - audienceMatchPolicy defines how the "audiences" field is used to match the "aud" claim in the presented JWT. - Allowed values are: - 1. "MatchAny" when multiple audiences are specified and - 2. empty (or unset) or "MatchAny" when a single audience is specified. - - - MatchAny: the "aud" claim in the presented JWT must match at least one of the entries in the "audiences" field. - For example, if "audiences" is ["foo", "bar"], the "aud" claim in the presented JWT must contain either "foo" or "bar" (and may contain both). - - - "": The match policy can be empty (or unset) when a single audience is specified in the "audiences" field. The "aud" claim in the presented JWT must contain the single audience (and may contain others). - - For more nuanced audience validation, use claimValidationRules. - example: claimValidationRule[].expression: 'sets.equivalent(claims.aud, ["bar", "foo", "baz"])' to require an exact match. - type: string - audiences: - description: |- - audiences is the set of acceptable audiences the JWT must be issued to. - At least one of the entries must match the "aud" claim in presented JWTs. - Same value as the --oidc-client-id flag (though this field supports an array). - Required to be non-empty. - items: - type: string - type: array - certificateAuthority: - description: |- - certificateAuthority contains PEM-encoded certificate authority certificates - used to validate the connection when fetching discovery information. - If unset, the system verifier is used. - Same value as the content of the file referenced by the --oidc-ca-file flag. - type: string - discoveryURL: - description: |- - discoveryURL, if specified, overrides the URL used to fetch discovery - information instead of using "{url}/.well-known/openid-configuration". - The exact value specified is used, so "/.well-known/openid-configuration" - must be included in discoveryURL if needed. - - The "issuer" field in the fetched discovery information must match the "issuer.url" field - in the AuthenticationConfiguration and will be used to validate the "iss" claim in the presented JWT. - This is for scenarios where the well-known and jwks endpoints are hosted at a different - location than the issuer (such as locally in the cluster). - - Example: - A discovery url that is exposed using kubernetes service 'oidc' in namespace 'oidc-namespace' - and discovery information is available at '/.well-known/openid-configuration'. - discoveryURL: "https://oidc.oidc-namespace/.well-known/openid-configuration" - certificateAuthority is used to verify the TLS connection and the hostname on the leaf certificate - must be set to 'oidc.oidc-namespace'. - - curl https://oidc.oidc-namespace/.well-known/openid-configuration (.discoveryURL field) - { - issuer: "https://oidc.example.com" (.url field) - } - - discoveryURL must be different from url. - Required to be unique across all JWT authenticators. - Note that egress selection configuration is not used for this network connection. - type: string - egressSelectorType: - description: |- - egressSelectorType is an indicator of which egress selection should be used for sending all traffic related - to this issuer (discovery, JWKS, distributed claims, etc). If unspecified, no custom dialer is used. - When specified, the valid choices are "controlplane" and "cluster". These correspond to the associated - values in the --egress-selector-config-file. - - - controlplane: for traffic intended to go to the control plane. - - - cluster: for traffic intended to go to the system being managed by Kubernetes. - type: string - url: - description: |- - url points to the issuer URL in a format https://url or https://url/path. - This must match the "iss" claim in the presented JWT, and the issuer returned from discovery. - Same value as the --oidc-issuer-url flag. - Discovery information is fetched from "{url}/.well-known/openid-configuration" unless overridden by discoveryURL. - Required to be unique across all JWT authenticators. - Note that egress selection configuration is not used for this network connection. - type: string - required: - - audiences - - url - type: object - userValidationRules: - description: |- - userValidationRules are rules that are applied to final user before completing authentication. - These allow invariants to be applied to incoming identities such as preventing the - use of the system: prefix that is commonly used by Kubernetes components. - The validation rules are logically ANDed together and must all return true for the validation to pass. - items: - description: UserValidationRule provides the configuration - for a single user info validation rule. - properties: - expression: - description: |- - expression represents the expression which will be evaluated by CEL. - Must return true for the validation to pass. - - CEL expressions have access to the contents of UserInfo, organized into CEL variable: - - 'user' - authentication.k8s.io/v1, Kind=UserInfo object - Refer to https://github.com/kubernetes/api/blob/release-1.28/authentication/v1/types.go#L105-L122 for the definition. - API documentation: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#userinfo-v1-authentication-k8s-io - - Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ - type: string - message: - description: |- - message customizes the returned error message when rule returns false. - message is a literal string. - type: string - required: - - expression - type: object - type: array - required: - - claimMappings - - issuer - type: object - type: array - k8s: - description: |- - Kubernetes authentication configuration. - Enables authentication using Kubernetes service account tokens. - Useful for integrating with existing Kubernetes RBAC policies. - properties: - enabled: - default: false - description: |- - Enable Kubernetes authentication. - When enabled, clients can authenticate using Kubernetes service account tokens. - type: boolean - type: object - type: object - baseDomain: - description: |- - Base domain used to construct FQDNs for all service endpoints. - This domain will be used to generate the default hostnames for Routes, Ingresses, and certificates. - Example: "example.com" will generate endpoints like "grpc.example.com", "router.example.com" - pattern: ^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$ - type: string - certManager: - description: |- - CertManager configuration for automatic TLS certificate management. - When enabled, jumpstarter will interact with cert-manager to automatically provision - and renew TLS certificates for all endpoints. Requires cert-manager to be installed in the cluster. - properties: - enabled: - default: false - description: |- - Enable cert-manager integration for automatic TLS certificate management. - When disabled, TLS certificates must be provided manually via secrets. - type: boolean - server: - description: |- - Server certificate configuration for controller and router endpoints. - Defines how server TLS certificates are issued. - properties: - issuerRef: - description: |- - Reference an existing cert-manager Issuer or ClusterIssuer. - Use this to integrate with existing PKI infrastructure (ACME, Vault, etc.). - This overrides SelfSigned.Enabled = true which is the default setting - properties: - caBundle: - description: |- - CABundle is an optional base64-encoded PEM CA certificate bundle for this issuer. - Required when using external issuers with non-publicly-trusted CAs. - This will be published to the {name}-service-ca-cert ConfigMap for clients to use. - For self-signed CA mode, this is automatically calculated from the CA secret. - format: byte - type: string - group: - default: cert-manager.io - description: |- - Group of the issuer resource. Defaults to cert-manager.io. - Only change this if using a custom issuer from a different API group. - type: string - kind: - default: Issuer - description: 'Kind of the issuer: "Issuer" for namespace-scoped - or "ClusterIssuer" for cluster-scoped.' - enum: - - Issuer - - ClusterIssuer - type: string - name: - description: Name of the Issuer or ClusterIssuer resource. - minLength: 1 - type: string - required: - - name - type: object - selfSigned: - description: |- - Create a self-signed CA managed by the operator. - The operator will create a self-signed Issuer and CA certificate, - then use that CA to issue server certificates. - properties: - caDuration: - default: 87600h - description: |- - Duration of the CA certificate validity. - The CA certificate is used to sign server certificates. - type: string - certDuration: - default: 8760h - description: |- - Duration of server certificate validity. - Server certificates are issued for controller and router endpoints. - type: string - enabled: - default: true - description: Enable self-signed CA mode. - type: boolean - renewBefore: - default: 360h - description: |- - Time before certificate expiration to trigger renewal. - Certificates will be renewed this duration before they expire. - type: string - type: object - type: object - type: object - controller: - default: {} - description: |- - Controller configuration for the main Jumpstarter API and gRPC services. - The controller handles gRPC and REST API requests from clients and exporters. - properties: - exporterOptions: - description: |- - Exporter options configuration. - Controls how exporters connect and behave when communicating with the controller. - properties: - offlineTimeout: - default: 180s - description: |- - Offline timeout duration for exporters. - After this duration without communication, an exporter is considered offline. - This drives the online/offline status field of exporters, and offline exporters - won't be considered for leases. - type: string - type: object - grpc: - description: |- - gRPC configuration for controller endpoints. - Defines how controller gRPC services are exposed and configured. - properties: - endpoints: - description: |- - List of gRPC endpoints to expose. - Each endpoint can use different networking methods (Route, Ingress, NodePort, or LoadBalancer) - based on your cluster setup. Example: Use Route for OpenShift, Ingress for standard Kubernetes. - items: - description: |- - Endpoint defines a single endpoint configuration. - An endpoint can use one or more networking methods: Route, Ingress, NodePort, or LoadBalancer. - Multiple methods can be configured simultaneously for the same address. - properties: - address: - description: |- - Address for this endpoint in the format "hostname", "hostname:port", "IPv4", "IPv4:port", "[IPv6]", or "[IPv6]:port". - Required for Route and Ingress endpoints. Optional for NodePort and LoadBalancer endpoints. - When optional, the address is used for certificate generation and DNS resolution. - Supports templating with $(replica) for replica-specific addresses. - Examples: "grpc.example.com", "grpc.example.com:9090", "192.168.1.1:8080", "[2001:db8::1]:8443", "router-$(replica).example.com" - pattern: ^(\[[0-9a-fA-F:\.]+\]|[0-9]+(\.[0-9]+){3}|[a-z0-9$]([a-z0-9\-\.\$\(\)]*[a-z0-9\)])?)(:[0-9]+)?$ - type: string - clusterIP: - description: |- - ClusterIP configuration for internal service access. - Creates a ClusterIP service for this endpoint. - Useful for internal service-to-service communication or when - using a different method to expose the service externally. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the ClusterIP service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the ClusterIP service for this endpoint. - When disabled, no ClusterIP service will be created for this endpoint. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the ClusterIP service. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - ingress: - description: |- - Ingress configuration for standard Kubernetes clusters. - Creates an Ingress resource for this endpoint. - Requires an ingress controller to be installed. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the Kubernetes Ingress resource. - Useful for configuring ingress-specific behavior, TLS settings, and load balancer options. - type: object - class: - default: default - description: |- - Ingress class name for the Kubernetes Ingress. - Specifies which ingress controller should handle this ingress. - type: string - enabled: - description: |- - Enable the Kubernetes Ingress for this endpoint. - When disabled, no Ingress resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the Kubernetes Ingress resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - loadBalancer: - description: |- - LoadBalancer configuration for cloud environments. - Creates a LoadBalancer service for this endpoint. - Requires cloud provider support for LoadBalancer services. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the LoadBalancer service. - Useful for configuring cloud provider-specific load balancer options. - Example: "service.beta.kubernetes.io/aws-load-balancer-type: nlb" - type: object - enabled: - description: |- - Enable the LoadBalancer service for this endpoint. - When disabled, no LoadBalancer service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the LoadBalancer service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - Port number for the LoadBalancer service. - Must be a valid port number (1-65535). - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - nodeport: - description: |- - NodePort configuration for direct node access. - Exposes the service on a specific port on each node. - Useful for bare-metal or simple cluster setups. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the NodePort service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the NodePort service for this endpoint. - When disabled, no NodePort service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the NodePort service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - NodePort port number to expose on each node. - Must be in the range 30000-32767 for most Kubernetes clusters. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - route: - description: |- - Route configuration for OpenShift clusters. - Creates an OpenShift Route resource for this endpoint. - Only applicable in OpenShift environments. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the OpenShift Route resource. - Useful for configuring route-specific behavior and TLS settings. - type: object - enabled: - description: |- - Enable the OpenShift Route for this endpoint. - When disabled, no Route resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the OpenShift Route resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - type: object - type: array - keepalive: - description: |- - Keepalive configuration for gRPC connections. - Controls connection health checks and idle connection management. - Helps maintain stable connections in load-balanced environments. - properties: - intervalTime: - default: 10s - description: |- - Interval between keepalive pings. - How often to send keepalive pings to check connection health. This is important - to keep TCP gRPC connections alive when traversing load balancers and proxies. - type: string - maxConnectionAge: - description: |- - Maximum age of a connection before it is closed and recreated. - Helps prevent issues with long-lived connections. It defaults to infinity. - type: string - maxConnectionAgeGrace: - description: |- - Grace period for closing connections that exceed MaxConnectionAge. - Allows ongoing RPCs to complete before closing the connection. - type: string - maxConnectionIdle: - description: |- - Maximum time a connection can remain idle before being closed. - It defaults to infinity. - type: string - minTime: - default: 1s - description: |- - Minimum time between keepalives that the connection will accept, under this threshold - the other side will get a GOAWAY signal. - Prevents excessive keepalive traffic on the network. - type: string - permitWithoutStream: - default: true - description: |- - Allow keepalive pings even when there are no active RPC streams. - Useful for detecting connection issues in idle connections. - This is important to keep TCP gRPC connections alive when traversing - load balancers and proxies. - type: boolean - timeout: - default: 180s - description: |- - Timeout for keepalive ping acknowledgment. - If a ping is not acknowledged within this time, the connection is considered broken. - The default is high to avoid issues when the network on a exporter is overloaded, i.e. - during flashing. - type: string - type: object - tls: - description: |- - TLS configuration for secure gRPC communication. - Requires a Kubernetes secret containing the TLS certificate and private key. - If spec.certManager.enabled is true, this secret will be automatically managed and - configured by cert-manager. - properties: - certSecret: - description: |- - Name of the Kubernetes secret containing the TLS certificate and private key. - The secret must contain 'tls.crt' and 'tls.key' keys. - If useCertManager is enabled, this secret will be automatically managed and - configured by cert-manager. - pattern: ^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$ - type: string - type: object - type: object - image: - default: quay.io/jumpstarter-dev/jumpstarter-controller:latest - description: |- - Container image for the controller pods in 'registry/repository/image:tag' format. - If not specified, defaults to the latest stable version of the Jumpstarter controller. - type: string - imagePullPolicy: - default: IfNotPresent - description: |- - Image pull policy for the controller container. - Controls when the container image should be pulled from the registry. - enum: - - Always - - IfNotPresent - - Never - type: string - login: - description: |- - Login endpoint configuration for simplified CLI login. - Provides authentication configuration discovery for the jmp login command. - The login service runs on HTTP and expects TLS to be terminated at the Route/Ingress level. - properties: - endpoints: - description: |- - List of login endpoints to expose. - Each endpoint can use different networking methods (Route, Ingress, NodePort, or LoadBalancer) - based on your cluster setup. - Note: Unlike gRPC endpoints, login endpoints use edge TLS termination (not passthrough). - items: - description: |- - Endpoint defines a single endpoint configuration. - An endpoint can use one or more networking methods: Route, Ingress, NodePort, or LoadBalancer. - Multiple methods can be configured simultaneously for the same address. - properties: - address: - description: |- - Address for this endpoint in the format "hostname", "hostname:port", "IPv4", "IPv4:port", "[IPv6]", or "[IPv6]:port". - Required for Route and Ingress endpoints. Optional for NodePort and LoadBalancer endpoints. - When optional, the address is used for certificate generation and DNS resolution. - Supports templating with $(replica) for replica-specific addresses. - Examples: "grpc.example.com", "grpc.example.com:9090", "192.168.1.1:8080", "[2001:db8::1]:8443", "router-$(replica).example.com" - pattern: ^(\[[0-9a-fA-F:\.]+\]|[0-9]+(\.[0-9]+){3}|[a-z0-9$]([a-z0-9\-\.\$\(\)]*[a-z0-9\)])?)(:[0-9]+)?$ - type: string - clusterIP: - description: |- - ClusterIP configuration for internal service access. - Creates a ClusterIP service for this endpoint. - Useful for internal service-to-service communication or when - using a different method to expose the service externally. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the ClusterIP service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the ClusterIP service for this endpoint. - When disabled, no ClusterIP service will be created for this endpoint. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the ClusterIP service. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - ingress: - description: |- - Ingress configuration for standard Kubernetes clusters. - Creates an Ingress resource for this endpoint. - Requires an ingress controller to be installed. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the Kubernetes Ingress resource. - Useful for configuring ingress-specific behavior, TLS settings, and load balancer options. - type: object - class: - default: default - description: |- - Ingress class name for the Kubernetes Ingress. - Specifies which ingress controller should handle this ingress. - type: string - enabled: - description: |- - Enable the Kubernetes Ingress for this endpoint. - When disabled, no Ingress resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the Kubernetes Ingress resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - loadBalancer: - description: |- - LoadBalancer configuration for cloud environments. - Creates a LoadBalancer service for this endpoint. - Requires cloud provider support for LoadBalancer services. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the LoadBalancer service. - Useful for configuring cloud provider-specific load balancer options. - Example: "service.beta.kubernetes.io/aws-load-balancer-type: nlb" - type: object - enabled: - description: |- - Enable the LoadBalancer service for this endpoint. - When disabled, no LoadBalancer service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the LoadBalancer service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - Port number for the LoadBalancer service. - Must be a valid port number (1-65535). - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - nodeport: - description: |- - NodePort configuration for direct node access. - Exposes the service on a specific port on each node. - Useful for bare-metal or simple cluster setups. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the NodePort service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the NodePort service for this endpoint. - When disabled, no NodePort service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the NodePort service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - NodePort port number to expose on each node. - Must be in the range 30000-32767 for most Kubernetes clusters. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - route: - description: |- - Route configuration for OpenShift clusters. - Creates an OpenShift Route resource for this endpoint. - Only applicable in OpenShift environments. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the OpenShift Route resource. - Useful for configuring route-specific behavior and TLS settings. - type: object - enabled: - description: |- - Enable the OpenShift Route for this endpoint. - When disabled, no Route resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the OpenShift Route resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - type: object - type: array - tls: - description: |- - TLS configuration for the login endpoint. - Specifies the Kubernetes secret containing the TLS certificate for edge termination. - If not specified and certManager is enabled, a default secret name will be generated. - properties: - secretName: - description: |- - Name of the Kubernetes secret containing the TLS certificate and private key. - The secret must contain 'tls.crt' and 'tls.key' keys. - Used for edge TLS termination at the Ingress/Route level. - pattern: ^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$ - type: string - type: object - type: object - replicas: - default: 2 - description: |- - Number of controller replicas to run. - Must be a positive integer. Minimum recommended value is 2 for high availability. - format: int32 - minimum: 1 - type: integer - resources: - description: |- - Resource requirements for controller pods. - Defines CPU and memory requests and limits for each controller pod. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This field depends on the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - 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: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - 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: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restApi: - description: |- - REST API configuration for HTTP-based clients. - Enables non-gRPC clients to interact with Jumpstarter for listing leases, - managing exporters, and creating new leases. Use this when you need HTTP/JSON access. - properties: - endpoints: - description: |- - List of REST API endpoints to expose. - Each endpoint can use different networking methods (Route, Ingress, NodePort, or LoadBalancer) - based on your cluster setup. - items: - description: |- - Endpoint defines a single endpoint configuration. - An endpoint can use one or more networking methods: Route, Ingress, NodePort, or LoadBalancer. - Multiple methods can be configured simultaneously for the same address. - properties: - address: - description: |- - Address for this endpoint in the format "hostname", "hostname:port", "IPv4", "IPv4:port", "[IPv6]", or "[IPv6]:port". - Required for Route and Ingress endpoints. Optional for NodePort and LoadBalancer endpoints. - When optional, the address is used for certificate generation and DNS resolution. - Supports templating with $(replica) for replica-specific addresses. - Examples: "grpc.example.com", "grpc.example.com:9090", "192.168.1.1:8080", "[2001:db8::1]:8443", "router-$(replica).example.com" - pattern: ^(\[[0-9a-fA-F:\.]+\]|[0-9]+(\.[0-9]+){3}|[a-z0-9$]([a-z0-9\-\.\$\(\)]*[a-z0-9\)])?)(:[0-9]+)?$ - type: string - clusterIP: - description: |- - ClusterIP configuration for internal service access. - Creates a ClusterIP service for this endpoint. - Useful for internal service-to-service communication or when - using a different method to expose the service externally. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the ClusterIP service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the ClusterIP service for this endpoint. - When disabled, no ClusterIP service will be created for this endpoint. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the ClusterIP service. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - ingress: - description: |- - Ingress configuration for standard Kubernetes clusters. - Creates an Ingress resource for this endpoint. - Requires an ingress controller to be installed. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the Kubernetes Ingress resource. - Useful for configuring ingress-specific behavior, TLS settings, and load balancer options. - type: object - class: - default: default - description: |- - Ingress class name for the Kubernetes Ingress. - Specifies which ingress controller should handle this ingress. - type: string - enabled: - description: |- - Enable the Kubernetes Ingress for this endpoint. - When disabled, no Ingress resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the Kubernetes Ingress resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - loadBalancer: - description: |- - LoadBalancer configuration for cloud environments. - Creates a LoadBalancer service for this endpoint. - Requires cloud provider support for LoadBalancer services. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the LoadBalancer service. - Useful for configuring cloud provider-specific load balancer options. - Example: "service.beta.kubernetes.io/aws-load-balancer-type: nlb" - type: object - enabled: - description: |- - Enable the LoadBalancer service for this endpoint. - When disabled, no LoadBalancer service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the LoadBalancer service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - Port number for the LoadBalancer service. - Must be a valid port number (1-65535). - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - nodeport: - description: |- - NodePort configuration for direct node access. - Exposes the service on a specific port on each node. - Useful for bare-metal or simple cluster setups. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the NodePort service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the NodePort service for this endpoint. - When disabled, no NodePort service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the NodePort service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - NodePort port number to expose on each node. - Must be in the range 30000-32767 for most Kubernetes clusters. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - route: - description: |- - Route configuration for OpenShift clusters. - Creates an OpenShift Route resource for this endpoint. - Only applicable in OpenShift environments. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the OpenShift Route resource. - Useful for configuring route-specific behavior and TLS settings. - type: object - enabled: - description: |- - Enable the OpenShift Route for this endpoint. - When disabled, no Route resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the OpenShift Route resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - type: object - type: array - tls: - description: |- - TLS configuration for secure HTTP communication. - Requires a Kubernetes secret containing the TLS certificate and private key. - properties: - certSecret: - description: |- - Name of the Kubernetes secret containing the TLS certificate and private key. - The secret must contain 'tls.crt' and 'tls.key' keys. - If useCertManager is enabled, this secret will be automatically managed and - configured by cert-manager. - pattern: ^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$ - type: string - type: object - type: object - type: object - routers: - default: {} - description: |- - Router configuration for the Jumpstarter router service. - Routers handle gRPC traffic routing and load balancing. - properties: - grpc: - description: |- - gRPC configuration for router endpoints. - Defines how router gRPC services are exposed and configured. - properties: - endpoints: - description: |- - List of gRPC endpoints to expose. - Each endpoint can use different networking methods (Route, Ingress, NodePort, or LoadBalancer) - based on your cluster setup. Example: Use Route for OpenShift, Ingress for standard Kubernetes. - items: - description: |- - Endpoint defines a single endpoint configuration. - An endpoint can use one or more networking methods: Route, Ingress, NodePort, or LoadBalancer. - Multiple methods can be configured simultaneously for the same address. - properties: - address: - description: |- - Address for this endpoint in the format "hostname", "hostname:port", "IPv4", "IPv4:port", "[IPv6]", or "[IPv6]:port". - Required for Route and Ingress endpoints. Optional for NodePort and LoadBalancer endpoints. - When optional, the address is used for certificate generation and DNS resolution. - Supports templating with $(replica) for replica-specific addresses. - Examples: "grpc.example.com", "grpc.example.com:9090", "192.168.1.1:8080", "[2001:db8::1]:8443", "router-$(replica).example.com" - pattern: ^(\[[0-9a-fA-F:\.]+\]|[0-9]+(\.[0-9]+){3}|[a-z0-9$]([a-z0-9\-\.\$\(\)]*[a-z0-9\)])?)(:[0-9]+)?$ - type: string - clusterIP: - description: |- - ClusterIP configuration for internal service access. - Creates a ClusterIP service for this endpoint. - Useful for internal service-to-service communication or when - using a different method to expose the service externally. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the ClusterIP service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the ClusterIP service for this endpoint. - When disabled, no ClusterIP service will be created for this endpoint. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the ClusterIP service. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - ingress: - description: |- - Ingress configuration for standard Kubernetes clusters. - Creates an Ingress resource for this endpoint. - Requires an ingress controller to be installed. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the Kubernetes Ingress resource. - Useful for configuring ingress-specific behavior, TLS settings, and load balancer options. - type: object - class: - default: default - description: |- - Ingress class name for the Kubernetes Ingress. - Specifies which ingress controller should handle this ingress. - type: string - enabled: - description: |- - Enable the Kubernetes Ingress for this endpoint. - When disabled, no Ingress resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the Kubernetes Ingress resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - loadBalancer: - description: |- - LoadBalancer configuration for cloud environments. - Creates a LoadBalancer service for this endpoint. - Requires cloud provider support for LoadBalancer services. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the LoadBalancer service. - Useful for configuring cloud provider-specific load balancer options. - Example: "service.beta.kubernetes.io/aws-load-balancer-type: nlb" - type: object - enabled: - description: |- - Enable the LoadBalancer service for this endpoint. - When disabled, no LoadBalancer service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the LoadBalancer service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - Port number for the LoadBalancer service. - Must be a valid port number (1-65535). - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - nodeport: - description: |- - NodePort configuration for direct node access. - Exposes the service on a specific port on each node. - Useful for bare-metal or simple cluster setups. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the NodePort service. - Useful for configuring service-specific behavior and load balancer options. - type: object - enabled: - description: |- - Enable the NodePort service for this endpoint. - When disabled, no NodePort service will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the NodePort service. - Useful for monitoring, cost allocation, and resource organization. - type: object - port: - description: |- - NodePort port number to expose on each node. - Must be in the range 30000-32767 for most Kubernetes clusters. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - route: - description: |- - Route configuration for OpenShift clusters. - Creates an OpenShift Route resource for this endpoint. - Only applicable in OpenShift environments. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations to add to the OpenShift Route resource. - Useful for configuring route-specific behavior and TLS settings. - type: object - enabled: - description: |- - Enable the OpenShift Route for this endpoint. - When disabled, no Route resource will be created for this endpoint. - When not specified, the operator will determine the best networking option for your cluster. - type: boolean - labels: - additionalProperties: - type: string - description: |- - Labels to add to the OpenShift Route resource. - Useful for monitoring, cost allocation, and resource organization. - type: object - type: object - type: object - type: array - keepalive: - description: |- - Keepalive configuration for gRPC connections. - Controls connection health checks and idle connection management. - Helps maintain stable connections in load-balanced environments. - properties: - intervalTime: - default: 10s - description: |- - Interval between keepalive pings. - How often to send keepalive pings to check connection health. This is important - to keep TCP gRPC connections alive when traversing load balancers and proxies. - type: string - maxConnectionAge: - description: |- - Maximum age of a connection before it is closed and recreated. - Helps prevent issues with long-lived connections. It defaults to infinity. - type: string - maxConnectionAgeGrace: - description: |- - Grace period for closing connections that exceed MaxConnectionAge. - Allows ongoing RPCs to complete before closing the connection. - type: string - maxConnectionIdle: - description: |- - Maximum time a connection can remain idle before being closed. - It defaults to infinity. - type: string - minTime: - default: 1s - description: |- - Minimum time between keepalives that the connection will accept, under this threshold - the other side will get a GOAWAY signal. - Prevents excessive keepalive traffic on the network. - type: string - permitWithoutStream: - default: true - description: |- - Allow keepalive pings even when there are no active RPC streams. - Useful for detecting connection issues in idle connections. - This is important to keep TCP gRPC connections alive when traversing - load balancers and proxies. - type: boolean - timeout: - default: 180s - description: |- - Timeout for keepalive ping acknowledgment. - If a ping is not acknowledged within this time, the connection is considered broken. - The default is high to avoid issues when the network on a exporter is overloaded, i.e. - during flashing. - type: string - type: object - tls: - description: |- - TLS configuration for secure gRPC communication. - Requires a Kubernetes secret containing the TLS certificate and private key. - If spec.certManager.enabled is true, this secret will be automatically managed and - configured by cert-manager. - properties: - certSecret: - description: |- - Name of the Kubernetes secret containing the TLS certificate and private key. - The secret must contain 'tls.crt' and 'tls.key' keys. - If useCertManager is enabled, this secret will be automatically managed and - configured by cert-manager. - pattern: ^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$ - type: string - type: object - type: object - image: - default: quay.io/jumpstarter-dev/jumpstarter-controller:latest - description: |- - Container image for the router pods in 'registry/repository/image:tag' format. - If not specified, defaults to the latest stable version of the Jumpstarter router. - type: string - imagePullPolicy: - default: IfNotPresent - description: |- - Image pull policy for the router container. - Controls when the container image should be pulled from the registry. - enum: - - Always - - IfNotPresent - - Never - type: string - replicas: - default: 3 - description: |- - Number of router replicas to run. - Must be a positive integer. Minimum recommended value is 3 for high availability. - format: int32 - minimum: 1 - type: integer - resources: - description: |- - Resource requirements for router pods. - Defines CPU and memory requests and limits for each router pod. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This field depends on the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - 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: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - 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: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - topologySpreadConstraints: - description: |- - Topology spread constraints for router pod distribution. - Ensures router pods are distributed evenly across nodes and zones. - Useful for high availability and fault tolerance. - items: - description: TopologySpreadConstraint specifies how to spread - matching pods among the given topology. - properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - format: int32 - type: integer - nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - If this value is nil, the behavior is equivalent to the Honor policy. - type: string - nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - If this value is nil, the behavior is equivalent to the Ignore policy. - type: string - topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - type: object - type: object - status: - description: |- - JumpstarterStatus defines the observed state of Jumpstarter. - Status information is reported through conditions following Kubernetes conventions. - properties: - conditions: - description: |- - Conditions represent the latest available observations of the Jumpstarter state. - Condition types include: - - CertManagerAvailable: cert-manager CRDs are installed in the cluster - - IssuerReady: The referenced or created issuer is ready to issue certificates - - ControllerCertificateReady: Controller TLS certificate is issued and secret exists - - RouterCertificatesReady: All router TLS certificates are issued and secrets exist - - ControllerDeploymentReady: Controller deployment is available - - RouterDeploymentsReady: All router deployments are available - - Ready: Overall system ready (aggregates all other conditions) - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.3 - name: leases.jumpstarter.dev -spec: - group: jumpstarter.dev - names: - kind: Lease - listKind: LeaseList - plural: leases - singular: lease - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.ended - name: Ended - type: boolean - - jsonPath: .spec.clientRef.name - name: Client - type: string - - jsonPath: .status.exporterRef.name - name: Exporter - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: Lease is the Schema for the exporters 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: LeaseSpec defines the desired state of Lease - properties: - beginTime: - description: |- - Requested start time. If omitted, lease starts when exporter is acquired. - Immutable after lease starts (cannot change the past). - format: date-time - type: string - clientRef: - description: The client that is requesting the lease - properties: - 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 - type: object - x-kubernetes-map-type: atomic - duration: - description: |- - Duration of the lease. Must be positive when provided. - Can be omitted (nil) when both BeginTime and EndTime are provided, - in which case it's calculated as EndTime - BeginTime. - type: string - endTime: - description: |- - Requested end time. If specified with BeginTime, Duration is calculated. - Can be updated to extend or shorten active leases. - format: date-time - type: string - release: - description: The release flag requests the controller to end the lease - now - type: boolean - selector: - description: The selector for the exporter to be used - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - required: - - clientRef - - selector - type: object - status: - description: LeaseStatus defines the observed state of Lease - properties: - beginTime: - description: |- - If the lease has been acquired an exporter name is assigned - and then it can be used, it will be empty while still pending - format: date-time - type: string - conditions: - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - endTime: - format: date-time - type: string - ended: - type: boolean - exporterRef: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - 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 - type: object - x-kubernetes-map-type: atomic - priority: - type: integer - spotAccess: - type: boolean - required: - - ended - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - name: jumpstarter-operator-controller-manager - namespace: jumpstarter-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - name: jumpstarter-operator-leader-election-role - namespace: jumpstarter-operator-system -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 ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - name: jumpstarter-operator-jumpstarter-admin-role -rules: -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters - verbs: - - '*' -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters/status - verbs: - - get ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - name: jumpstarter-operator-jumpstarter-editor-role -rules: -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters/status - verbs: - - get ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - name: jumpstarter-operator-jumpstarter-viewer-role -rules: -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters - verbs: - - get - - list - - watch -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters/status - verbs: - - get ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: jumpstarter-operator-manager-role -rules: -- apiGroups: - - "" - resources: - - configmaps - - secrets - - serviceaccounts - - services - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - "" - resources: - - events - verbs: - - create - - patch -- apiGroups: - - "" - resources: - - services/status - verbs: - - get - - patch - - update -- apiGroups: - - apps - resources: - - deployments - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - apps - resources: - - deployments/status - verbs: - - get - - patch - - update -- apiGroups: - - cert-manager.io - resources: - - certificates - - issuers - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - cert-manager.io - resources: - - certificates/status - - clusterissuers/status - - issuers/status - verbs: - - get -- apiGroups: - - cert-manager.io - resources: - - clusterissuers - verbs: - - get - - list - - watch -- apiGroups: - - config.openshift.io - resources: - - ingresses - verbs: - - get - - list - - watch -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - jumpstarter.dev - resources: - - clients - - exporteraccesspolicies - - exporters - - leases - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - jumpstarter.dev - resources: - - clients/finalizers - - exporteraccesspolicies/finalizers - - exporters/finalizers - - leases/finalizers - verbs: - - update -- apiGroups: - - jumpstarter.dev - resources: - - clients/status - - exporteraccesspolicies/status - - exporters/status - - leases/status - verbs: - - get - - patch - - update -- apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - networking.k8s.io - resources: - - ingresses - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - networking.k8s.io - resources: - - ingresses/status - verbs: - - get - - patch - - update -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters/finalizers - verbs: - - update -- apiGroups: - - operator.jumpstarter.dev - resources: - - jumpstarters/status - verbs: - - get - - patch - - update -- apiGroups: - - rbac.authorization.k8s.io - resources: - - rolebindings - - roles - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - route.openshift.io - resources: - - routes - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - route.openshift.io - resources: - - routes/custom-host - verbs: - - create - - get - - patch - - update -- apiGroups: - - route.openshift.io - resources: - - routes/status - verbs: - - get - - patch - - update ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: jumpstarter-operator-metrics-auth-role -rules: -- apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create -- apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - name: jumpstarter-operator-metrics-reader -rules: -- nonResourceURLs: - - /metrics - verbs: - - get ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - name: jumpstarter-operator-leader-election-rolebinding - namespace: jumpstarter-operator-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: jumpstarter-operator-leader-election-role -subjects: -- kind: ServiceAccount - name: jumpstarter-operator-controller-manager - namespace: jumpstarter-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - name: jumpstarter-operator-manager-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: jumpstarter-operator-manager-role -subjects: -- kind: ServiceAccount - name: jumpstarter-operator-controller-manager - namespace: jumpstarter-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: jumpstarter-operator-metrics-auth-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: jumpstarter-operator-metrics-auth-role -subjects: -- kind: ServiceAccount - name: jumpstarter-operator-controller-manager - namespace: jumpstarter-operator-system ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - control-plane: controller-manager - name: jumpstarter-operator-controller-manager-metrics-service - namespace: jumpstarter-operator-system -spec: - ports: - - name: https - port: 8443 - protocol: TCP - targetPort: 8443 - selector: - app.kubernetes.io/name: jumpstarter-operator - control-plane: controller-manager ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: jumpstarter-operator - control-plane: controller-manager - name: jumpstarter-operator-controller-manager - namespace: jumpstarter-operator-system -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: jumpstarter-operator - control-plane: controller-manager - template: - metadata: - annotations: - kubectl.kubernetes.io/default-container: manager - labels: - app.kubernetes.io/name: jumpstarter-operator - control-plane: controller-manager - spec: - containers: - - args: - - --metrics-bind-address=:8443 - - --leader-elect - - --health-probe-bind-address=:8081 - command: - - /manager - image: quay.io/jumpstarter-dev/jumpstarter-operator:latest - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: /healthz - port: 8081 - initialDelaySeconds: 15 - periodSeconds: 20 - name: manager - ports: [] - readinessProbe: - httpGet: - path: /readyz - port: 8081 - initialDelaySeconds: 5 - periodSeconds: 10 - resources: - limits: - cpu: 500m - memory: 512Mi - requests: - cpu: 10m - memory: 256Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - volumeMounts: [] - securityContext: - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - serviceAccountName: jumpstarter-operator-controller-manager - terminationGracePeriodSeconds: 10 - volumes: [] diff --git a/controller/internal/service/login/service.go b/controller/internal/service/login/service.go index 056f06107..4ea8e4b3a 100644 --- a/controller/internal/service/login/service.go +++ b/controller/internal/service/login/service.go @@ -21,6 +21,7 @@ import ( "embed" "encoding/base64" "html/template" + "net" "net/http" "os" "time" @@ -131,6 +132,17 @@ func (s *Service) Start(ctx context.Context) error { }) port := getEnvOrDefault("LOGIN_SERVICE_PORT", defaultPort) + // Normalize into a valid net.Listen address. + // If it's already a host:port (or [IPv6]:port), keep it as-is. + // Otherwise treat it as a bare port and prepend ":". + if port != "" { + if _, _, err := net.SplitHostPort(port); err != nil { + // Not a valid host:port — assume bare port (e.g. "8086") + if port[0] != ':' { + port = ":" + port + } + } + } server := &http.Server{ Addr: port,