From 12b680e33579b05d4fb0370dc3ccc249a3e94e06 Mon Sep 17 00:00:00 2001 From: Miguel Angel Ajo Pelayo Date: Fri, 6 Feb 2026 14:50:47 +0100 Subject: [PATCH 1/6] operator: stop shipping the bundle & install in repo Those files can be regenerated anytime from our code with: ``` cd controller/deploy/operator make bundle make build-installer ``` --- .github/workflows/controller-bundle.yaml | 94 - ...er-manager-metrics-service_v1_service.yaml | 20 - ...c.authorization.k8s.io_v1_clusterrole.yaml | 21 - ...c.authorization.k8s.io_v1_clusterrole.yaml | 27 - ...c.authorization.k8s.io_v1_clusterrole.yaml | 23 - ...c.authorization.k8s.io_v1_clusterrole.yaml | 13 - ...tarter-operator.clusterserviceversion.yaml | 431 --- .../manifests/jumpstarter.dev_clients.yaml | 75 - ...umpstarter.dev_exporteraccesspolicies.yaml | 172 - .../manifests/jumpstarter.dev_exporters.yaml | 166 - .../manifests/jumpstarter.dev_leases.yaml | 241 -- ...operator.jumpstarter.dev_jumpstarters.yaml | 1911 ---------- .../operator/bundle/metadata/annotations.yaml | 14 - .../bundle/tests/scorecard/config.yaml | 70 - controller/deploy/operator/dist/install.yaml | 3067 ----------------- 15 files changed, 6345 deletions(-) delete mode 100644 .github/workflows/controller-bundle.yaml delete mode 100644 controller/deploy/operator/bundle/manifests/jumpstarter-operator-controller-manager-metrics-service_v1_service.yaml delete mode 100644 controller/deploy/operator/bundle/manifests/jumpstarter-operator-jumpstarter-admin-role_rbac.authorization.k8s.io_v1_clusterrole.yaml delete mode 100644 controller/deploy/operator/bundle/manifests/jumpstarter-operator-jumpstarter-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml delete mode 100644 controller/deploy/operator/bundle/manifests/jumpstarter-operator-jumpstarter-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml delete mode 100644 controller/deploy/operator/bundle/manifests/jumpstarter-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml delete mode 100644 controller/deploy/operator/bundle/manifests/jumpstarter-operator.clusterserviceversion.yaml delete mode 100644 controller/deploy/operator/bundle/manifests/jumpstarter.dev_clients.yaml delete mode 100644 controller/deploy/operator/bundle/manifests/jumpstarter.dev_exporteraccesspolicies.yaml delete mode 100644 controller/deploy/operator/bundle/manifests/jumpstarter.dev_exporters.yaml delete mode 100644 controller/deploy/operator/bundle/manifests/jumpstarter.dev_leases.yaml delete mode 100644 controller/deploy/operator/bundle/manifests/operator.jumpstarter.dev_jumpstarters.yaml delete mode 100644 controller/deploy/operator/bundle/metadata/annotations.yaml delete mode 100644 controller/deploy/operator/bundle/tests/scorecard/config.yaml delete mode 100644 controller/deploy/operator/dist/install.yaml 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/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/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: [] From 8e8505747102b6d6791432acba01984dfcbe8a89 Mon Sep 17 00:00:00 2001 From: Miguel Angel Ajo Pelayo Date: Fri, 6 Feb 2026 14:52:58 +0100 Subject: [PATCH 2/6] operator: fix warnings, add icon, and examples At the same time, we are disabling the client, lease, exporter, exporterpolicy CRDs from the view of the operator, since the operator only manages the "Jumpstarter" CRDs for deployment, everything else is noise and confusion to the admin. --- controller/api/v1alpha1/client_types.go | 3 + controller/api/v1alpha1/exporter_types.go | 7 ++ .../v1alpha1/exporteraccesspolicy_types.go | 2 + controller/api/v1alpha1/lease_types.go | 8 +++ ...tarter-operator.clusterserviceversion.yaml | 70 ++++++++++++++++++- .../samples/jumpstarter_v1alpha1_client.yaml | 8 +++ .../jumpstarter_v1alpha1_exporter.yaml | 7 ++ ...starter_v1alpha1_exporteraccesspolicy.yaml | 13 ++++ .../samples/jumpstarter_v1alpha1_lease.yaml | 11 +++ .../config/samples/kustomization.yaml | 4 ++ 10 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 controller/deploy/operator/config/samples/jumpstarter_v1alpha1_client.yaml create mode 100644 controller/deploy/operator/config/samples/jumpstarter_v1alpha1_exporter.yaml create mode 100644 controller/deploy/operator/config/samples/jumpstarter_v1alpha1_exporteraccesspolicy.yaml create mode 100644 controller/deploy/operator/config/samples/jumpstarter_v1alpha1_lease.yaml 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..bddc4446b 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 ran 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/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml b/controller/deploy/operator/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml index 8ac483465..fff4ad924 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,76 @@ 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": {}, + "clientSelector": {} + } } ] capabilities: Basic Install + operators.operatorframework.io/internal-objects: '["clients.jumpstarter.dev","exporters.jumpstarter.dev","leases.jumpstarter.dev","exporteraccesspolicies.jumpstarter.dev"]' 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 +97,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 +126,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..bf3121b8f --- /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: "keycloak: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 From e5c08242a22e891f3b3b3d8d4aaebad8cfba6e67 Mon Sep 17 00:00:00 2001 From: Miguel Angel Ajo Pelayo Date: Fri, 6 Feb 2026 16:17:26 +0100 Subject: [PATCH 3/6] operator: contribution to upstream repos --- controller/deploy/operator/Makefile | 11 ++- ...tarter-operator.clusterserviceversion.yaml | 10 +++ .../deploy/operator/contribute/.gitignore | 2 + .../contribute/update-contributions.sh | 76 +++++++++++++++++++ 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 controller/deploy/operator/contribute/.gitignore create mode 100755 controller/deploy/operator/contribute/update-contributions.sh diff --git a/controller/deploy/operator/Makefile b/controller/deploy/operator/Makefile index b87499dad..d7b50a066 100644 --- a/controller/deploy/operator/Makefile +++ b/controller/deploy/operator/Makefile @@ -3,7 +3,7 @@ # 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.7.5 # 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,8 +305,17 @@ 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: v4.18-v4.21' >> bundle/metadata/annotations.yaml; \ + fi $(OPERATOR_SDK) bundle validate ./bundle +.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. $(CONTAINER_TOOL) build -f bundle.Dockerfile -t $(BUNDLE_IMG) . 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 fff4ad924..7267dcc59 100644 --- a/controller/deploy/operator/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml +++ b/controller/deploy/operator/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml @@ -55,7 +55,17 @@ metadata: } ] 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: 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..ad2c2f665 --- /dev/null +++ b/controller/deploy/operator/contribute/update-contributions.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +# 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" + +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}') +echo "Bundle version: ${VERSION}" + +# 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" + 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" && 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" && git add -A && 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 $dir && git push -f user ${BRANCH}" +done From 861c675518ec4fe488837abbdf14c40f142bab19 Mon Sep 17 00:00:00 2001 From: Miguel Angel Ajo Pelayo Date: Fri, 6 Feb 2026 17:28:48 +0100 Subject: [PATCH 4/6] easy-login: ensure listening on the :port --- .../internal/controller/jumpstarter/jumpstarter_controller.go | 2 +- controller/internal/service/login/service.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go b/controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go index 20e170593..fe314a1e2 100644 --- a/controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go +++ b/controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go @@ -751,7 +751,7 @@ func (r *JumpstarterReconciler) createControllerDeployment(jumpstarter *operator Args: []string{ "--leader-elect", "--health-probe-bind-address=:8081", - "-metrics-bind-address=:8080", + "--metrics-bind-address=:8080", }, Env: envVars, VolumeMounts: volumeMounts, diff --git a/controller/internal/service/login/service.go b/controller/internal/service/login/service.go index 056f06107..1db0c5896 100644 --- a/controller/internal/service/login/service.go +++ b/controller/internal/service/login/service.go @@ -131,6 +131,10 @@ func (s *Service) Start(ctx context.Context) error { }) port := getEnvOrDefault("LOGIN_SERVICE_PORT", defaultPort) + // Ensure port has the ":" prefix for net.Listen format + if port != "" && port[0] != ':' { + port = ":" + port + } server := &http.Server{ Addr: port, From dd3fbf578cb946e54cb647c08738ab8499e3ecd8 Mon Sep 17 00:00:00 2001 From: Miguel Angel Ajo Pelayo Date: Mon, 9 Feb 2026 17:35:32 +0100 Subject: [PATCH 5/6] operator 0.8.1-rc1 reviews --- controller/api/v1alpha1/exporter_types.go | 2 +- controller/deploy/operator/Makefile | 7 +++- ...tarter-operator.clusterserviceversion.yaml | 3 +- .../samples/jumpstarter_v1alpha1_client.yaml | 2 +- .../contribute/update-contributions.sh | 42 +++++++++++++++++-- .../jumpstarter/jumpstarter_controller.go | 2 +- controller/internal/service/login/service.go | 14 +++++-- 7 files changed, 60 insertions(+), 12 deletions(-) diff --git a/controller/api/v1alpha1/exporter_types.go b/controller/api/v1alpha1/exporter_types.go index bddc4446b..c7fd22ddb 100644 --- a/controller/api/v1alpha1/exporter_types.go +++ b/controller/api/v1alpha1/exporter_types.go @@ -55,7 +55,7 @@ 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 ran on a linux machine, or a pod, with the exporter credentials + // 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 diff --git a/controller/deploy/operator/Makefile b/controller/deploy/operator/Makefile index d7b50a066..11d9daac2 100644 --- a/controller/deploy/operator/Makefile +++ b/controller/deploy/operator/Makefile @@ -3,7 +3,10 @@ # 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.7.5 +VERSION ?= 0.8.1-rc1 + +# 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") @@ -307,7 +310,7 @@ bundle: manifests kustomize operator-sdk ## Generate bundle manifests and metada $(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: v4.18-v4.21' >> bundle/metadata/annotations.yaml; \ + echo ' com.redhat.openshift.versions: $(OPENSHIFT_VERSIONS)' >> bundle/metadata/annotations.yaml; \ fi $(OPERATOR_SDK) bundle validate ./bundle 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 7267dcc59..50d21979e 100644 --- a/controller/deploy/operator/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml +++ b/controller/deploy/operator/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml @@ -50,7 +50,7 @@ metadata: }, "spec": { "exporterSelector": {}, - "clientSelector": {} + "policies": [{"from": [{"clientSelector": {}}]}] } } ] @@ -70,6 +70,7 @@ metadata: namespace: placeholder spec: apiservicedefinitions: {} + replaces: jumpstarter-operator.v0.8.0 customresourcedefinitions: owned: - description: Client represents a user identity for accessing the Jumpstarter diff --git a/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_client.yaml b/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_client.yaml index bf3121b8f..98e8e7d42 100644 --- a/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_client.yaml +++ b/controller/deploy/operator/config/samples/jumpstarter_v1alpha1_client.yaml @@ -5,4 +5,4 @@ metadata: labels: type: developer spec: - username: "keycloak:user-name-in-keycloak" + username: "kc:user-name-in-keycloak" diff --git a/controller/deploy/operator/contribute/update-contributions.sh b/controller/deploy/operator/contribute/update-contributions.sh index ad2c2f665..dad7418c6 100755 --- a/controller/deploy/operator/contribute/update-contributions.sh +++ b/controller/deploy/operator/contribute/update-contributions.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -euo pipefail # Target repos: "clone-url local-directory" # Add or remove entries here to sync to more/fewer upstreams. @@ -22,8 +23,43 @@ if [ ! -f "$CSV_PATH" ]; then 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 echo "Bundle version: ${VERSION}" +REPLACES=$(grep "^ replaces:" "$CSV_PATH" | awk '{print $2}') +if [ -z "$REPLACES" ]; then + echo "Error: 'spec.replaces' is not set in $CSV_PATH" >&2 + echo "Set 'replaces: jumpstarter-operator.vX.Y.Z' in the CSV base before contributing." >&2 + exit 1 +fi + +REPLACES_VERSION="${REPLACES#jumpstarter-operator.v}" +if [ "$REPLACES_VERSION" = "$VERSION" ]; then + echo "Error: 'spec.replaces' version ($REPLACES_VERSION) is the same as the bundle version ($VERSION)." >&2 + echo "Update 'replaces' in the CSV base to point to the previous release." >&2 + exit 1 +fi + +echo "" +echo "============================================" +echo " Bundle version : ${VERSION}" +echo " Replaces : ${REPLACES} (v${REPLACES_VERSION})" +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 in: ${OPERATOR_DIR}/Makefile" + echo " - replaces in: ${OPERATOR_DIR}/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml" + 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" @@ -40,7 +76,7 @@ for entry in "${COMMUNITY_OPS[@]}"; do # Add or update the "user" remote for the fork ( - cd "$dir" + cd "$dir" || exit 1 if git remote get-url user &>/dev/null; then git remote set-url user "$user_fork" else @@ -55,7 +91,7 @@ BRANCH="jumpstarter-operator-release-${VERSION}" for entry in "${COMMUNITY_OPS[@]}"; do read -r url dir <<< "$entry" echo "--- $dir: switching to branch $BRANCH ---" - (cd "$dir" && git fetch --all && git checkout remotes/origin/main -B "$BRANCH") + (cd "$dir" || exit 1; git fetch --all && git checkout remotes/origin/main -B "$BRANCH") done # Copy bundle into each repo and commit @@ -65,7 +101,7 @@ for entry in "${COMMUNITY_OPS[@]}"; do echo "Updating ${dir} to version ${VERSION}" mkdir -p "$dest" cp -v -r -f "${BUNDLE_DIR}"/* "$dest" - (cd "$dir" && git add -A && git commit -s -m "operator jumpstarter-operator (${VERSION})") + (cd "$dir" || exit 1; git add -A && git commit -s -m "operator jumpstarter-operator (${VERSION})") done echo "" diff --git a/controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go b/controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go index fe314a1e2..20e170593 100644 --- a/controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go +++ b/controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go @@ -751,7 +751,7 @@ func (r *JumpstarterReconciler) createControllerDeployment(jumpstarter *operator Args: []string{ "--leader-elect", "--health-probe-bind-address=:8081", - "--metrics-bind-address=:8080", + "-metrics-bind-address=:8080", }, Env: envVars, VolumeMounts: volumeMounts, diff --git a/controller/internal/service/login/service.go b/controller/internal/service/login/service.go index 1db0c5896..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,9 +132,16 @@ func (s *Service) Start(ctx context.Context) error { }) port := getEnvOrDefault("LOGIN_SERVICE_PORT", defaultPort) - // Ensure port has the ":" prefix for net.Listen format - if port != "" && port[0] != ':' { - port = ":" + port + // 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{ From c94a9666441fb0da0231b5b9feda6c95a3bcb7d2 Mon Sep 17 00:00:00 2001 From: Miguel Angel Ajo Pelayo Date: Mon, 9 Feb 2026 18:38:01 +0100 Subject: [PATCH 6/6] operator: handle contributions using FBC --- controller/deploy/operator/Makefile | 22 +++++++- ...tarter-operator.clusterserviceversion.yaml | 1 - .../contribute/update-contributions.sh | 53 +++++++++++++------ 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/controller/deploy/operator/Makefile b/controller/deploy/operator/Makefile index 11d9daac2..15f337e72 100644 --- a/controller/deploy/operator/Makefile +++ b/controller/deploy/operator/Makefile @@ -3,7 +3,16 @@ # 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.1-rc1 +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 @@ -313,6 +322,17 @@ bundle: manifests kustomize operator-sdk ## Generate bundle manifests and metada 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. 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 50d21979e..d5fa1b039 100644 --- a/controller/deploy/operator/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml +++ b/controller/deploy/operator/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml @@ -70,7 +70,6 @@ metadata: namespace: placeholder spec: apiservicedefinitions: {} - replaces: jumpstarter-operator.v0.8.0 customresourcedefinitions: owned: - description: Client represents a user identity for accessing the Jumpstarter diff --git a/controller/deploy/operator/contribute/update-contributions.sh b/controller/deploy/operator/contribute/update-contributions.sh index dad7418c6..4c5ab49e9 100755 --- a/controller/deploy/operator/contribute/update-contributions.sh +++ b/controller/deploy/operator/contribute/update-contributions.sh @@ -15,6 +15,7 @@ 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" @@ -28,34 +29,56 @@ if [ -z "$VERSION" ]; then echo "Expected a line matching '^ version:' in $CSV_PATH but got nothing." >&2 exit 1 fi -echo "Bundle version: ${VERSION}" -REPLACES=$(grep "^ replaces:" "$CSV_PATH" | awk '{print $2}') -if [ -z "$REPLACES" ]; then - echo "Error: 'spec.replaces' is not set in $CSV_PATH" >&2 - echo "Set 'replaces: jumpstarter-operator.vX.Y.Z' in the CSV base before contributing." >&2 +# 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_VERSION="${REPLACES#jumpstarter-operator.v}" -if [ "$REPLACES_VERSION" = "$VERSION" ]; then - echo "Error: 'spec.replaces' version ($REPLACES_VERSION) is the same as the bundle version ($VERSION)." >&2 - echo "Update 'replaces' in the CSV base to point to the previous release." >&2 - exit 1 +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 " Replaces : ${REPLACES} (v${REPLACES_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 in: ${OPERATOR_DIR}/Makefile" - echo " - replaces in: ${OPERATOR_DIR}/config/manifests/bases/jumpstarter-operator.clusterserviceversion.yaml" + 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 @@ -101,12 +124,12 @@ for entry in "${COMMUNITY_OPS[@]}"; do echo "Updating ${dir} to version ${VERSION}" mkdir -p "$dest" cp -v -r -f "${BUNDLE_DIR}"/* "$dest" - (cd "$dir" || exit 1; git add -A && git commit -s -m "operator jumpstarter-operator (${VERSION})") + (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 $dir && git push -f user ${BRANCH}" + echo " cd contribute/$dir && git push -f user ${BRANCH}" done