From 11e409442a068fdc9653af2654e7527e9eeb20a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20M=C3=B6ller?= Date: Fri, 14 Jun 2024 10:41:36 +0200 Subject: [PATCH] feat!: replace topolvm with lvms --- assets/components/lvms/csi-driver.yaml | 14 - .../lvms/lvm.topolvm.io_lvmclusters.yaml | 397 ++++++++++++++++++ ...topolvm.io_lvmvolumegroupnodestatuses.yaml | 114 +++++ .../lvms/lvm.topolvm.io_lvmvolumegroups.yaml | 209 +++++++++ ...ics_rbac.authorization.k8s.io_v1_role.yaml | 17 + ...c.authorization.k8s.io_v1_rolebinding.yaml | 14 + ...s-operator-metrics-service_v1_service.yaml | 21 + ...missionregistration.k8s.io_v1_webhook.yaml | 38 ++ .../lvms-operator_apps_v1_deployment.yaml | 88 ++++ ....authorization.k8s.io_v1_clusterrole.yaml} | 272 +++++++++--- ...ization.k8s.io_v1_clusterrolebinding.yaml} | 6 +- ...tor_rbac.authorization.k8s.io_v1_role.yaml | 37 ++ ....authorization.k8s.io_v1_rolebinding.yaml} | 6 +- ...l => lvms-operator_v1_serviceaccount.yaml} | 2 +- .../lvms/lvms-webhook-service_v1_service.yaml | 17 + .../lvms/lvms_default-lvmcluster.yaml | 5 + .../lvms/topolvm-configmap_lvms-version.yaml | 2 +- .../lvms/topolvm-controller_deployment.yaml | 150 ------- .../topolvm-lvmd-config_configmap_v1.yaml | 7 - ...c.authorization.k8s.io_v1_clusterrole.yaml | 13 - ...opolvm-node-securitycontextconstraint.yaml | 32 -- .../lvms/topolvm-node_daemonset.yaml | 152 ------- ...vg-manager-metrics-service_v1_service.yaml | 21 + ....authorization.k8s.io_v1_clusterrole.yaml} | 26 +- ...ization.k8s.io_v1_clusterrolebinding.yaml} | 6 +- ...er_rbac.authorization.k8s.io_v1_role.yaml} | 63 ++- ....authorization.k8s.io_v1_rolebinding.yaml} | 12 +- ...yaml => vg-manager_v1_serviceaccount.yaml} | 2 +- assets/release/release-aarch64.json | 6 +- assets/release/release-x86_64.json | 6 +- pkg/assets/admission-registration.go | 2 +- pkg/assets/crd.go | 5 +- pkg/assets/storage.go | 56 +-- pkg/assets/unstructured.go | 208 +++++++++ pkg/assets/unstructured_test.go | 22 + pkg/components/render.go | 18 - pkg/components/storage.go | 144 ++++--- pkg/config/lvmd/lvmd.go | 16 +- pkg/util/unstructured.go | 65 +++ scripts/auto-rebase/last_lvms_rebase.sh | 2 +- scripts/auto-rebase/lvms_assets.yaml | 53 ++- scripts/auto-rebase/rebase-lvms.sh | 114 ++++- 42 files changed, 1785 insertions(+), 675 deletions(-) delete mode 100644 assets/components/lvms/csi-driver.yaml create mode 100644 assets/components/lvms/lvm.topolvm.io_lvmclusters.yaml create mode 100644 assets/components/lvms/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml create mode 100644 assets/components/lvms/lvm.topolvm.io_lvmvolumegroups.yaml create mode 100644 assets/components/lvms/lvms-metrics_rbac.authorization.k8s.io_v1_role.yaml create mode 100644 assets/components/lvms/lvms-metrics_rbac.authorization.k8s.io_v1_rolebinding.yaml create mode 100644 assets/components/lvms/lvms-operator-metrics-service_v1_service.yaml create mode 100644 assets/components/lvms/lvms-operator_admissionregistration.k8s.io_v1_webhook.yaml create mode 100644 assets/components/lvms/lvms-operator_apps_v1_deployment.yaml rename assets/components/lvms/{topolvm-controller_rbac.authorization.k8s.io_v1_clusterrole.yaml => lvms-operator_rbac.authorization.k8s.io_v1_clusterrole.yaml} (53%) rename assets/components/lvms/{topolvm-node-scc_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml => lvms-operator_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml} (74%) create mode 100644 assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_role.yaml rename assets/components/lvms/{topolvm-controller_rbac.authorization.k8s.io_v1_rolebinding.yaml => lvms-operator_rbac.authorization.k8s.io_v1_rolebinding.yaml} (75%) rename assets/components/lvms/{topolvm-controller_v1_serviceaccount.yaml => lvms-operator_v1_serviceaccount.yaml} (79%) create mode 100644 assets/components/lvms/lvms-webhook-service_v1_service.yaml create mode 100644 assets/components/lvms/lvms_default-lvmcluster.yaml delete mode 100644 assets/components/lvms/topolvm-controller_deployment.yaml delete mode 100644 assets/components/lvms/topolvm-lvmd-config_configmap_v1.yaml delete mode 100644 assets/components/lvms/topolvm-node-scc_rbac.authorization.k8s.io_v1_clusterrole.yaml delete mode 100644 assets/components/lvms/topolvm-node-securitycontextconstraint.yaml delete mode 100644 assets/components/lvms/topolvm-node_daemonset.yaml create mode 100644 assets/components/lvms/vg-manager-metrics-service_v1_service.yaml rename assets/components/lvms/{topolvm-node_rbac.authorization.k8s.io_v1_clusterrole.yaml => vg-manager_rbac.authorization.k8s.io_v1_clusterrole.yaml} (97%) rename assets/components/lvms/{topolvm-node_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml => vg-manager_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml} (76%) rename assets/components/lvms/{topolvm-controller_rbac.authorization.k8s.io_v1_role.yaml => vg-manager_rbac.authorization.k8s.io_v1_role.yaml} (60%) rename assets/components/lvms/{topolvm-controller_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml => vg-manager_rbac.authorization.k8s.io_v1_rolebinding.yaml} (51%) rename assets/components/lvms/{topolvm-node_v1_serviceaccount.yaml => vg-manager_v1_serviceaccount.yaml} (83%) create mode 100644 pkg/assets/unstructured.go create mode 100644 pkg/assets/unstructured_test.go create mode 100644 pkg/util/unstructured.go diff --git a/assets/components/lvms/csi-driver.yaml b/assets/components/lvms/csi-driver.yaml deleted file mode 100644 index 314d563e82e..00000000000 --- a/assets/components/lvms/csi-driver.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# Source: topolvm/templates/controller/csidriver.yaml -apiVersion: storage.k8s.io/v1 -kind: CSIDriver -metadata: - name: topolvm.io - labels: - security.openshift.io/csi-ephemeral-volume-profile: restricted -spec: - storageCapacity: true - attachRequired: false - podInfoOnMount: true - volumeLifecycleModes: - - Persistent - - Ephemeral diff --git a/assets/components/lvms/lvm.topolvm.io_lvmclusters.yaml b/assets/components/lvms/lvm.topolvm.io_lvmclusters.yaml new file mode 100644 index 00000000000..d12576f17ab --- /dev/null +++ b/assets/components/lvms/lvm.topolvm.io_lvmclusters.yaml @@ -0,0 +1,397 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + creationTimestamp: null + name: lvmclusters.lvm.topolvm.io +spec: + group: lvm.topolvm.io + names: + kind: LVMCluster + listKind: LVMClusterList + plural: lvmclusters + singular: lvmcluster + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.state + name: Status + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: LVMCluster is the Schema for the lvmclusters 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: LVMClusterSpec defines the desired state of LVMCluster + properties: + storage: + description: Storage contains the device class configuration for local + storage devices. + properties: + deviceClasses: + description: DeviceClasses contains the configuration to assign + the local storage devices to the LVM volume groups that you + can use to provision persistent volume claims (PVCs). + items: + properties: + default: + description: Default is a flag to indicate that a device + class is the default. You can configure only a single + default device class. + type: boolean + deviceSelector: + description: DeviceSelector contains the configuration to + specify paths to the devices that you want to add to the + LVM volume group, and force wipe the selected devices. + properties: + forceWipeDevicesAndDestroyAllData: + description: |- + ForceWipeDevicesAndDestroyAllData is a flag to force wipe the selected devices. + This wipes the file signatures on the devices. Use this feature with caution. + Force wipe the devices only when you know that they do not contain any important data. + type: boolean + optionalPaths: + description: OptionalPaths specify the optional device + paths. + items: + type: string + type: array + paths: + description: Paths specify the device paths. + items: + type: string + type: array + type: object + fstype: + default: xfs + description: FilesystemType sets the filesystem the device + should use. Select either `ext4` or `xfs`. + enum: + - xfs + - ext4 + - "" + type: string + name: + description: Name specifies a name for the device class + maxLength: 245 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + nodeSelector: + description: NodeSelector contains the configuration to + choose the nodes on which you want to create the LVM volume + group. If this field is not configured, all nodes without + no-schedule taints are considered. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + 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. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + 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. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + thinPoolConfig: + description: ThinPoolConfig contains the configuration to + create a thin pool in the LVM volume group. If you exclude + this field, logical volumes are thick provisioned. + properties: + chunkSize: + anyOf: + - type: integer + - type: string + description: |- + ChunkSize specifies the statically calculated chunk size for the thin pool. + Thus, It is only used when the ChunkSizeCalculationPolicy is set to Static. + No ChunkSize with a ChunkSizeCalculationPolicy set to Static will result in a default chunk size of 128Ki. + It can be between 64Ki and 1Gi due to the underlying limitations of lvm2. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + chunkSizeCalculationPolicy: + default: Static + description: |- + ChunkSizeCalculationPolicy specifies the policy to calculate the chunk size for the underlying volume. + When set to Host, the chunk size is calculated based on the lvm2 host setting on the node. + When set to Static, the chunk size is calculated based on the static size attribute provided within ChunkSize. + enum: + - Host + - Static + type: string + name: + description: Name specifies a name for the thin pool. + type: string + overprovisionRatio: + description: OverProvisionRatio specifies a factor by + which you can provision additional storage based on + the available storage in the thin pool. To prevent + over-provisioning through validation, set this field + to 1. + minimum: 1 + type: integer + sizePercent: + default: 90 + description: SizePercent specifies the percentage of + space in the LVM volume group for creating the thin + pool. + maximum: 90 + minimum: 10 + type: integer + required: + - name + - overprovisionRatio + type: object + type: object + type: array + type: object + tolerations: + description: Tolerations to apply to nodes to act on + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + status: + description: LVMClusterStatus defines the observed state of LVMCluster + properties: + conditions: + description: Conditions describes the state of the resource. + items: + description: |- + Condition represents the state of the operator's + reconciliation functionality. + properties: + lastHeartbeatTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + description: ConditionType is the state of the operator's reconciliation + functionality. + type: string + required: + - status + - type + type: object + type: array + deviceClassStatuses: + description: DeviceClassStatuses describes the status of all deviceClasses + items: + description: DeviceClassStatus defines the observed status of the + deviceclass across all nodes + properties: + name: + description: Name is the name of the deviceclass + type: string + nodeStatus: + description: NodeStatus tells if the deviceclass was created + on the node + items: + description: NodeStatus defines the observed state of the + deviceclass on the node + properties: + deviceDiscoveryPolicy: + default: RuntimeDynamic + description: |- + DeviceDiscoveryPolicy is a field to indicate whether the devices are discovered + at runtime or preconfigured through a DeviceSelector + Setting this to DeviceDiscoveryPolicyPreconfigured indicates the devices are preconfigured through a DeviceSelector. + Setting this to DeviceDiscoveryPolicyRuntimeDynamic indicates the devices are added to the VG dynamically if they are present at runtime. + By default, the value is set to RuntimeDynamic. + enum: + - Preconfigured + - RuntimeDynamic + type: string + devices: + description: Devices is the list of devices used by the + volume group + items: + type: string + type: array + excluded: + description: |- + Excluded contains the per node status of applied device exclusions that were picked up via selector, + but were not used for other reasons. + items: + properties: + name: + description: Name is the device that was filtered + type: string + reasons: + description: Reasons are the human-readable reasons + why the device was excluded from the volume group + items: + type: string + type: array + required: + - name + - reasons + type: object + type: array + name: + description: Name is the name of the volume group + type: string + node: + description: Node is the name of the node + type: string + reason: + description: Reason provides more detail on the volume + group creation status + type: string + status: + description: Status tells if the volume group was created + on the node + type: string + type: object + type: array + type: object + type: array + ready: + description: Ready describes if the LVMCluster is ready. + type: boolean + state: + description: State describes the LVMCluster state. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/assets/components/lvms/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml b/assets/components/lvms/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml new file mode 100644 index 00000000000..eea44e27156 --- /dev/null +++ b/assets/components/lvms/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml @@ -0,0 +1,114 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + creationTimestamp: null + name: lvmvolumegroupnodestatuses.lvm.topolvm.io +spec: + group: lvm.topolvm.io + names: + kind: LVMVolumeGroupNodeStatus + listKind: LVMVolumeGroupNodeStatusList + plural: lvmvolumegroupnodestatuses + singular: lvmvolumegroupnodestatus + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: LVMVolumeGroupNodeStatus is the Schema for the lvmvolumegroupnodestatuses + 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: LVMVolumeGroupNodeStatusSpec defines the desired state of + LVMVolumeGroupNodeStatus + properties: + nodeStatus: + description: NodeStatus contains the per node status of the VG + items: + properties: + deviceDiscoveryPolicy: + default: RuntimeDynamic + description: |- + DeviceDiscoveryPolicy is a field to indicate whether the devices are discovered + at runtime or preconfigured through a DeviceSelector + Setting this to DeviceDiscoveryPolicyPreconfigured indicates the devices are preconfigured through a DeviceSelector. + Setting this to DeviceDiscoveryPolicyRuntimeDynamic indicates the devices are added to the VG dynamically if they are present at runtime. + By default, the value is set to RuntimeDynamic. + enum: + - Preconfigured + - RuntimeDynamic + type: string + devices: + description: Devices is the list of devices used by the volume + group + items: + type: string + type: array + excluded: + description: |- + Excluded contains the per node status of applied device exclusions that were picked up via selector, + but were not used for other reasons. + items: + properties: + name: + description: Name is the device that was filtered + type: string + reasons: + description: Reasons are the human-readable reasons why + the device was excluded from the volume group + items: + type: string + type: array + required: + - name + - reasons + type: object + type: array + name: + description: Name is the name of the volume group + type: string + reason: + description: Reason provides more detail on the volume group + creation status + type: string + status: + description: Status tells if the volume group was created on + the node + type: string + type: object + type: array + type: object + status: + description: LVMVolumeGroupNodeStatusStatus defines the observed state + of LVMVolumeGroupNodeStatus + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/assets/components/lvms/lvm.topolvm.io_lvmvolumegroups.yaml b/assets/components/lvms/lvm.topolvm.io_lvmvolumegroups.yaml new file mode 100644 index 00000000000..2d279461951 --- /dev/null +++ b/assets/components/lvms/lvm.topolvm.io_lvmvolumegroups.yaml @@ -0,0 +1,209 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + creationTimestamp: null + name: lvmvolumegroups.lvm.topolvm.io +spec: + group: lvm.topolvm.io + names: + kind: LVMVolumeGroup + listKind: LVMVolumeGroupList + plural: lvmvolumegroups + singular: lvmvolumegroup + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: LVMVolumeGroup is the Schema for the lvmvolumegroups 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: LVMVolumeGroupSpec defines the desired state of LVMVolumeGroup + properties: + default: + description: Default is a flag to indicate whether the device-class + is the default + type: boolean + deviceSelector: + description: DeviceSelector is a set of rules that should match for + a device to be included in this TopoLVMCluster + properties: + forceWipeDevicesAndDestroyAllData: + description: |- + ForceWipeDevicesAndDestroyAllData is a flag to force wipe the selected devices. + This wipes the file signatures on the devices. Use this feature with caution. + Force wipe the devices only when you know that they do not contain any important data. + type: boolean + optionalPaths: + description: OptionalPaths specify the optional device paths. + items: + type: string + type: array + paths: + description: Paths specify the device paths. + items: + type: string + type: array + type: object + nodeSelector: + description: NodeSelector chooses nodes + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms + are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements by node's + labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + 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. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements by node's + fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector applies + to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + 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. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + thinPoolConfig: + description: ThinPoolConfig contains configurations for the thin-pool + properties: + chunkSize: + anyOf: + - type: integer + - type: string + description: |- + ChunkSize specifies the statically calculated chunk size for the thin pool. + Thus, It is only used when the ChunkSizeCalculationPolicy is set to Static. + No ChunkSize with a ChunkSizeCalculationPolicy set to Static will result in a default chunk size of 128Ki. + It can be between 64Ki and 1Gi due to the underlying limitations of lvm2. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + chunkSizeCalculationPolicy: + default: Static + description: |- + ChunkSizeCalculationPolicy specifies the policy to calculate the chunk size for the underlying volume. + When set to Host, the chunk size is calculated based on the lvm2 host setting on the node. + When set to Static, the chunk size is calculated based on the static size attribute provided within ChunkSize. + enum: + - Host + - Static + type: string + name: + description: Name specifies a name for the thin pool. + type: string + overprovisionRatio: + description: OverProvisionRatio specifies a factor by which you + can provision additional storage based on the available storage + in the thin pool. To prevent over-provisioning through validation, + set this field to 1. + minimum: 1 + type: integer + sizePercent: + default: 90 + description: SizePercent specifies the percentage of space in + the LVM volume group for creating the thin pool. + maximum: 90 + minimum: 10 + type: integer + required: + - name + - overprovisionRatio + type: object + type: object + status: + description: LVMVolumeGroupStatus defines the observed state of LVMVolumeGroup + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/assets/components/lvms/lvms-metrics_rbac.authorization.k8s.io_v1_role.yaml b/assets/components/lvms/lvms-metrics_rbac.authorization.k8s.io_v1_role.yaml new file mode 100644 index 00000000000..626bb0f368f --- /dev/null +++ b/assets/components/lvms/lvms-metrics_rbac.authorization.k8s.io_v1_role.yaml @@ -0,0 +1,17 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + creationTimestamp: null + name: lvms-metrics + namespace: openshift-storage +rules: + - apiGroups: + - "" + resources: + - services + - endpoints + - pods + verbs: + - get + - list + - watch diff --git a/assets/components/lvms/lvms-metrics_rbac.authorization.k8s.io_v1_rolebinding.yaml b/assets/components/lvms/lvms-metrics_rbac.authorization.k8s.io_v1_rolebinding.yaml new file mode 100644 index 00000000000..d5dc71a9aee --- /dev/null +++ b/assets/components/lvms/lvms-metrics_rbac.authorization.k8s.io_v1_rolebinding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + creationTimestamp: null + name: lvms-metrics + namespace: openshift-storage +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: lvms-metrics +subjects: + - kind: ServiceAccount + name: prometheus-k8s + namespace: openshift-monitoring diff --git a/assets/components/lvms/lvms-operator-metrics-service_v1_service.yaml b/assets/components/lvms/lvms-operator-metrics-service_v1_service.yaml new file mode 100644 index 00000000000..066fd567402 --- /dev/null +++ b/assets/components/lvms/lvms-operator-metrics-service_v1_service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + service.beta.openshift.io/serving-cert-secret-name: lvms-operator-metrics-cert + creationTimestamp: null + labels: + app.kubernetes.io/compose: metrics + app.kubernetes.io/name: lvms-operator + name: lvms-operator-metrics-service + namespace: openshift-storage +spec: + ports: + - name: https + port: 443 + protocol: TCP + targetPort: 8443 + selector: + app.kubernetes.io/name: lvms-operator +status: + loadBalancer: {} diff --git a/assets/components/lvms/lvms-operator_admissionregistration.k8s.io_v1_webhook.yaml b/assets/components/lvms/lvms-operator_admissionregistration.k8s.io_v1_webhook.yaml new file mode 100644 index 00000000000..237e9aa6e75 --- /dev/null +++ b/assets/components/lvms/lvms-operator_admissionregistration.k8s.io_v1_webhook.yaml @@ -0,0 +1,38 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + namespace: openshift-storage + name: vlvmcluster.kb.io-lvms-operator + annotations: + service.beta.openshift.io/inject-cabundle: "true" +webhooks: + - name: vlvmcluster.kb.io + clientConfig: + service: + name: lvms-webhook-service + namespace: openshift-storage + path: /validate-lvm-topolvm-io-v1alpha1-lvmcluster + port: 443 + rules: + - apiGroups: + - lvm.topolvm.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - lvmclusters + scope: '*' + failurePolicy: Fail + matchPolicy: Equivalent + sideEffects: None + timeoutSeconds: 10 + admissionReviewVersions: + - v1 + namespaceSelector: + matchExpressions: + - key: namespace + operator: In + values: + - openshift-storage diff --git a/assets/components/lvms/lvms-operator_apps_v1_deployment.yaml b/assets/components/lvms/lvms-operator_apps_v1_deployment.yaml new file mode 100644 index 00000000000..b12a0b2a9db --- /dev/null +++ b/assets/components/lvms/lvms-operator_apps_v1_deployment.yaml @@ -0,0 +1,88 @@ +label: + app.kubernetes.io/name: lvms-operator +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: lvms-operator + strategy: + type: Recreate + template: + metadata: + annotations: + target.workload.openshift.io/management: '{"effect": "PreferredDuringScheduling"}' + labels: + app.kubernetes.io/component: lvms-operator + app.kubernetes.io/name: lvms-operator + app.kubernetes.io/part-of: lvms-provisioner + spec: + containers: + - args: + - --health-probe-bind-address=:8081 + - --leader-elect=false + command: + - /lvms + - operator + env: + - name: GOGC + value: "120" + - name: GOMEMLIMIT + value: 50MiB + - name: GOMAXPROCS + value: "2" + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + image: quay.io/jmoller/lvms-operator:microshift + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 10 + periodSeconds: 20 + name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + resources: + requests: + cpu: 5m + memory: 50Mi + securityContext: + allowPrivilegeEscalation: false + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + - mountPath: /tmp/k8s-metrics-server/serving-certs + name: metrics-cert + readOnly: true + - mountPath: /run/topolvm + name: socket-dir + priorityClassName: openshift-user-critical + securityContext: + runAsNonRoot: true + serviceAccountName: lvms-operator + terminationGracePeriodSeconds: 10 + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: lvms-operator-webhook-server-cert + - name: metrics-cert + secret: + defaultMode: 420 + secretName: lvms-operator-metrics-cert + - emptyDir: {} + name: socket-dir +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openshift-storage + name: lvms-operator diff --git a/assets/components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_clusterrole.yaml b/assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_clusterrole.yaml similarity index 53% rename from assets/components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_clusterrole.yaml rename to assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_clusterrole.yaml index 93feb3a559e..c1eb320eac8 100644 --- a/assets/components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_clusterrole.yaml +++ b/assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_clusterrole.yaml @@ -1,210 +1,344 @@ rules: - apiGroups: - - "" + - apps resources: - - nodes + - daemonsets verbs: + - create + - delete - get - list - - watch - patch - update + - watch - apiGroups: - - "" + - apps resources: - - pods + - deployments verbs: + - create + - delete - get - list + - patch + - update - watch - - delete - apiGroups: - - "" + - apps resources: - - persistentvolumeclaims + - replicasets verbs: - get + - apiGroups: + - config.openshift.io + resources: + - infrastructures + verbs: + - get + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - delete + - get - list - - watch + - patch - update - - delete + - watch - apiGroups: - - storage.k8s.io + - "" resources: - - storageclasses - - csidrivers + - configmaps verbs: + - create + - delete - get - list + - patch + - update - watch + - apiGroups: + - "" + resources: + - events + verbs: - create + - list - patch - update + - watch - apiGroups: - - topolvm.io + - "" resources: - - logicalvolumes - - logicalvolumes/status + - node verbs: - get - list - watch - - create - - update - - patch - - delete - apiGroups: - "" resources: - - persistentvolumes + - nodes verbs: - get - list + - patch + - update - watch - - create - - delete - apiGroups: - "" resources: - persistentvolumeclaims verbs: + - delete - get - list - - watch - update + - watch - apiGroups: - - storage.k8s.io + - "" resources: - - storageclasses + - persistentvolumeclaims/status verbs: + - patch + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - create + - delete - get - list + - patch + - update - watch - apiGroups: - "" resources: - - events + - pods verbs: + - delete + - get - list - watch - - create - - update - - patch - apiGroups: - - snapshot.storage.k8s.io + - lvm.topolvm.io resources: - - volumesnapshots + - lvmclusters verbs: + - create + - delete - get - list + - patch + - update + - watch - apiGroups: - - snapshot.storage.k8s.io + - lvm.topolvm.io resources: - - volumesnapshotcontents + - lvmclusters/finalizers + verbs: + - update + - apiGroups: + - lvm.topolvm.io + resources: + - lvmclusters/status verbs: - get - - list + - patch + - update - apiGroups: - - storage.k8s.io + - lvm.topolvm.io resources: - - csinodes + - lvmvolumegroupnodestatuses verbs: + - create + - delete - get - list + - patch + - update - watch - apiGroups: - - "" + - lvm.topolvm.io resources: - - nodes + - lvmvolumegroupnodestatuses/finalizers + verbs: + - update + - apiGroups: + - lvm.topolvm.io + resources: + - lvmvolumegroupnodestatuses/status verbs: - get - - list - - watch + - patch + - update - apiGroups: - - storage.k8s.io + - lvm.topolvm.io resources: - - volumeattachments + - lvmvolumegroups verbs: + - create + - delete - get - list + - patch + - update - watch - apiGroups: - - "" + - lvm.topolvm.io resources: - - persistentvolumes + - lvmvolumegroups/finalizers + verbs: + - update + - apiGroups: + - lvm.topolvm.io + resources: + - lvmvolumegroups/status verbs: + - get + - patch + - update + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - create + - delete - get - list - - watch - patch + - update + - watch - apiGroups: - - "" + - snapshot.storage.k8s.io resources: - - persistentvolumeclaims + - volumesnapshotclasses verbs: + - create + - delete - get - list + - patch + - update - watch - apiGroups: - - "" + - snapshot.storage.k8s.io resources: - - pods + - volumesnapshotcontents verbs: - get - list + - patch + - update - watch - apiGroups: - - "" + - snapshot.storage.k8s.io resources: - - persistentvolumeclaims/status + - volumesnapshotcontents/status verbs: - patch + - update - apiGroups: - - "" + - snapshot.storage.k8s.io resources: - - events + - volumesnapshots verbs: + - get - list - - watch + - apiGroups: + - storage.k8s.io + resources: + - csidrivers + verbs: - create - - update + - delete + - get + - list - patch + - update + - watch - apiGroups: - - "" + - storage.k8s.io resources: - - events + - csinodes verbs: + - get + - list - watch + - apiGroups: + - storage.k8s.io + resources: + - csistoragecapacities + verbs: + - create + - delete + - get - list + - patch - update + - watch + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: - create + - delete + - get + - list - patch + - update + - watch - apiGroups: - - snapshot.storage.k8s.io + - storage.k8s.io resources: - - volumesnapshotclasses + - volumeattachments verbs: - get - - watch - list + - watch - apiGroups: - - snapshot.storage.k8s.io + - topolvm.io resources: - - volumesnapshotcontents + - logicalvolumes verbs: + - create + - delete - get - - watch - list - - update - patch + - update + - watch - apiGroups: - - snapshot.storage.k8s.io + - topolvm.io resources: - - volumesnapshotcontents/status + - logicalvolumes/status verbs: - - update + - create + - delete + - get + - list - patch + - update + - watch + - 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: - name: topolvm-controller + name: lvms-operator diff --git a/assets/components/lvms/topolvm-node-scc_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml b/assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml similarity index 74% rename from assets/components/lvms/topolvm-node-scc_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml rename to assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml index 2d24b592b35..0fd195b7248 100644 --- a/assets/components/lvms/topolvm-node-scc_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml +++ b/assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml @@ -1,12 +1,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: topolvm-node-scc + name: lvms-operator roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: topolvm-node-scc + name: lvms-operator subjects: - kind: ServiceAccount - name: topolvm-node + name: lvms-operator namespace: openshift-storage diff --git a/assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_role.yaml b/assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_role.yaml new file mode 100644 index 00000000000..ea1c3297fd0 --- /dev/null +++ b/assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_role.yaml @@ -0,0 +1,37 @@ +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: Role +metadata: + name: lvms-operator + namespace: openshift-storage diff --git a/assets/components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_rolebinding.yaml b/assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_rolebinding.yaml similarity index 75% rename from assets/components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_rolebinding.yaml rename to assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_rolebinding.yaml index 7ae10ec19b1..d80104cd495 100644 --- a/assets/components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_rolebinding.yaml +++ b/assets/components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_rolebinding.yaml @@ -1,14 +1,14 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: topolvm-controller + name: lvms-operator namespace: openshift-storage roleRef: apiGroup: rbac.authorization.k8s.io kind: Role - name: topolvm-controller + name: lvms-operator namespace: openshift-storage subjects: - kind: ServiceAccount - name: topolvm-controller + name: lvms-operator namespace: openshift-storage diff --git a/assets/components/lvms/topolvm-controller_v1_serviceaccount.yaml b/assets/components/lvms/lvms-operator_v1_serviceaccount.yaml similarity index 79% rename from assets/components/lvms/topolvm-controller_v1_serviceaccount.yaml rename to assets/components/lvms/lvms-operator_v1_serviceaccount.yaml index bebf599c3eb..ea8adf4e3b5 100644 --- a/assets/components/lvms/topolvm-controller_v1_serviceaccount.yaml +++ b/assets/components/lvms/lvms-operator_v1_serviceaccount.yaml @@ -2,5 +2,5 @@ apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: null - name: topolvm-controller + name: lvms-operator namespace: openshift-storage diff --git a/assets/components/lvms/lvms-webhook-service_v1_service.yaml b/assets/components/lvms/lvms-webhook-service_v1_service.yaml new file mode 100644 index 00000000000..44abb0c5220 --- /dev/null +++ b/assets/components/lvms/lvms-webhook-service_v1_service.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + service.beta.openshift.io/serving-cert-secret-name: lvms-operator-webhook-server-cert + creationTimestamp: null + name: lvms-webhook-service + namespace: openshift-storage +spec: + ports: + - port: 443 + protocol: TCP + targetPort: 9443 + selector: + app.kubernetes.io/name: lvms-operator +status: + loadBalancer: {} diff --git a/assets/components/lvms/lvms_default-lvmcluster.yaml b/assets/components/lvms/lvms_default-lvmcluster.yaml new file mode 100644 index 00000000000..272057e68f5 --- /dev/null +++ b/assets/components/lvms/lvms_default-lvmcluster.yaml @@ -0,0 +1,5 @@ +apiVersion: lvm.topolvm.io/v1alpha1 +kind: LVMCluster +metadata: + name: lvms + namespace: openshift-storage \ No newline at end of file diff --git a/assets/components/lvms/topolvm-configmap_lvms-version.yaml b/assets/components/lvms/topolvm-configmap_lvms-version.yaml index 30160ca2c54..5d52b48ff74 100644 --- a/assets/components/lvms/topolvm-configmap_lvms-version.yaml +++ b/assets/components/lvms/topolvm-configmap_lvms-version.yaml @@ -4,4 +4,4 @@ metadata: name: lvms-version namespace: kube-public data: - version: v4.15.0 + version: v4.16.0-58 diff --git a/assets/components/lvms/topolvm-controller_deployment.yaml b/assets/components/lvms/topolvm-controller_deployment.yaml deleted file mode 100644 index 02f179f43b2..00000000000 --- a/assets/components/lvms/topolvm-controller_deployment.yaml +++ /dev/null @@ -1,150 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: topolvm-controller - namespace: openshift-storage -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/component: topolvm-controller - app.kubernetes.io/name: topolvm-csi-driver - strategy: - type: Recreate - template: - metadata: - labels: - app.kubernetes.io/component: topolvm-controller - app.kubernetes.io/name: topolvm-csi-driver - name: topolvm-controller - namespace: openshift-storage - spec: - containers: - - command: - - /topolvm-controller - - --cert-dir=/certs - image: '{{ .ReleaseImage.topolvm_csi }}' - startupProbe: - failureThreshold: 60 - periodSeconds: 2 - timeoutSeconds: 3 - httpGet: - port: healthz - path: /healthz - livenessProbe: - httpGet: - port: healthz - path: /healthz - timeoutSeconds: 3 - failureThreshold: 3 - periodSeconds: 60 - readinessProbe: - httpGet: - port: readyz - path: /readyz - timeoutSeconds: 3 - failureThreshold: 3 - periodSeconds: 60 - name: topolvm-controller - ports: - - containerPort: 9808 - name: healthz - protocol: TCP - - containerPort: 8081 - name: readyz - protocol: TCP - - containerPort: 8080 - name: metrics - protocol: TCP - resources: - requests: - cpu: 2m - memory: 31Mi - terminationMessagePolicy: FallbackToLogsOnError - volumeMounts: - - mountPath: /run/topolvm - name: socket-dir - - mountPath: /certs - name: certs - - args: - - --csi-address=/run/topolvm/csi-topolvm.sock - - --enable-capacity - - --capacity-ownerref-level=2 - - --capacity-poll-interval=30s - - --feature-gates=Topology=true - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - image: '{{ .ReleaseImage.topolvm_csi_provisioner }}' - name: csi-provisioner - resources: - requests: - cpu: 2m - memory: 35Mi - terminationMessagePolicy: FallbackToLogsOnError - volumeMounts: - - mountPath: /run/topolvm - name: socket-dir - - args: - - --csi-address=/run/topolvm/csi-topolvm.sock - image: '{{ .ReleaseImage.topolvm_csi_resizer }}' - name: csi-resizer - resources: - requests: - cpu: 1m - memory: 23Mi - terminationMessagePolicy: FallbackToLogsOnError - volumeMounts: - - mountPath: /run/topolvm - name: socket-dir - - args: - - --csi-address=/run/topolvm/csi-topolvm.sock - image: '{{ .ReleaseImage.topolvm_csi_livenessprobe }}' - name: liveness-probe - resources: - requests: - cpu: 1m - memory: 9Mi - terminationMessagePolicy: FallbackToLogsOnError - volumeMounts: - - mountPath: /run/topolvm - name: socket-dir - - name: csi-snapshotter - image: '{{ .ReleaseImage.csi_external_snapshotter }}' - args: - - "--v=5" - - "--csi-address=$(ADDRESS)" - - "--leader-election=false" - env: - - name: ADDRESS - value: /csi/csi-topolvm.sock - imagePullPolicy: IfNotPresent - terminationMessagePolicy: FallbackToLogsOnError - volumeMounts: - - name: socket-dir - mountPath: /csi - initContainers: - - command: - - /usr/bin/bash - - -c - - openssl req -nodes -x509 -newkey rsa:4096 -subj '/DC=self_signed_certificate' - -keyout /certs/tls.key -out /certs/tls.crt -days 3650 - image: '{{ .ReleaseImage.openssl }}' - name: self-signed-cert-generator - resources: {} - terminationMessagePolicy: FallbackToLogsOnError - volumeMounts: - - mountPath: /certs - name: certs - serviceAccountName: topolvm-controller - volumes: - - emptyDir: {} - name: socket-dir - - emptyDir: {} - name: certs diff --git a/assets/components/lvms/topolvm-lvmd-config_configmap_v1.yaml b/assets/components/lvms/topolvm-lvmd-config_configmap_v1.yaml deleted file mode 100644 index d60daca7a07..00000000000 --- a/assets/components/lvms/topolvm-lvmd-config_configmap_v1.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -data: - lvmd.yaml: "" -kind: ConfigMap -metadata: - name: lvmd - namespace: openshift-storage diff --git a/assets/components/lvms/topolvm-node-scc_rbac.authorization.k8s.io_v1_clusterrole.yaml b/assets/components/lvms/topolvm-node-scc_rbac.authorization.k8s.io_v1_clusterrole.yaml deleted file mode 100644 index 38645d15f7c..00000000000 --- a/assets/components/lvms/topolvm-node-scc_rbac.authorization.k8s.io_v1_clusterrole.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: topolvm-node-scc -rules: -- apiGroups: - - security.openshift.io - resourceNames: - - topolvm-node - resources: - - securitycontextconstraints - verbs: - - use diff --git a/assets/components/lvms/topolvm-node-securitycontextconstraint.yaml b/assets/components/lvms/topolvm-node-securitycontextconstraint.yaml deleted file mode 100644 index f770749b8cb..00000000000 --- a/assets/components/lvms/topolvm-node-securitycontextconstraint.yaml +++ /dev/null @@ -1,32 +0,0 @@ -allowHostDirVolumePlugin: true -allowHostIPC: false -allowHostNetwork: false -allowHostPID: true -allowHostPorts: false -allowPrivilegeEscalation: true -allowPrivilegedContainer: true -allowedCapabilities: [] -apiVersion: security.openshift.io/v1 -defaultAddCapabilities: [] -fsGroup: - type: RunAsAny -groups: [] -kind: SecurityContextConstraints -metadata: - name: topolvm-node -priority: null -readOnlyRootFilesystem: false -requiredDropCapabilities: [] -runAsUser: - type: RunAsAny -seLinuxContext: - type: RunAsAny -supplementalGroups: - type: RunAsAny -users: -- system:serviceaccount:openshift-storage:topolvm-node -volumes: -- configMap -- emptyDir -- hostPath -- secret diff --git a/assets/components/lvms/topolvm-node_daemonset.yaml b/assets/components/lvms/topolvm-node_daemonset.yaml deleted file mode 100644 index 3e948a45ff6..00000000000 --- a/assets/components/lvms/topolvm-node_daemonset.yaml +++ /dev/null @@ -1,152 +0,0 @@ -apiVersion: apps/v1 -kind: DaemonSet -metadata: - labels: - app.kubernetes.io/component: topolvm-node - app.kubernetes.io/name: topolvm-csi-driver - name: topolvm-node - namespace: openshift-storage -spec: - selector: - matchLabels: - app.kubernetes.io/component: topolvm-node - app.kubernetes.io/name: topolvm-csi-driver - template: - metadata: - annotations: - lvms.microshift.io/lvmd_config_sha256sum: '{{ Sha256sum .lvmd }}' - labels: - app.kubernetes.io/component: topolvm-node - app.kubernetes.io/name: topolvm-csi-driver - spec: - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: kubernetes.io/os - operator: In - values: - - linux - containers: - - command: - - /topolvm-node - - --embed-lvmd - env: - - name: NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - image: '{{ .ReleaseImage.topolvm_csi }}' - livenessProbe: - httpGet: - port: healthz - path: /healthz - timeoutSeconds: 3 - failureThreshold: 3 - periodSeconds: 60 - startupProbe: - failureThreshold: 60 - periodSeconds: 2 - timeoutSeconds: 3 - httpGet: - port: healthz - path: /healthz - name: topolvm-node - ports: - - containerPort: 9808 - name: healthz - protocol: TCP - resources: - requests: - cpu: 2m - memory: 35Mi - securityContext: - privileged: true - runAsUser: 0 - terminationMessagePolicy: FallbackToLogsOnError - volumeMounts: - - mountPath: /etc/topolvm - name: lvmd-config-dir - - mountPath: /run/topolvm - name: node-plugin-dir - - mountPath: /var/lib/kubelet/pods - mountPropagation: Bidirectional - name: pod-volumes-dir - - mountPath: /var/lib/kubelet/plugins/kubernetes.io/csi - mountPropagation: Bidirectional - name: csi-plugin-dir - - args: - - --csi-address=/run/topolvm/csi-topolvm.sock - - --kubelet-registration-path=/var/lib/kubelet/plugins/topolvm.io/node/csi-topolvm.sock - image: '{{ .ReleaseImage.topolvm_csi_registrar }}' - lifecycle: - preStop: - exec: - command: - - /bin/sh - - -c - - rm -rf /registration/topolvm.io /registration/topolvm.io-reg.sock - name: csi-registrar - resources: - requests: - cpu: 1m - memory: 2Mi - terminationMessagePolicy: FallbackToLogsOnError - volumeMounts: - - mountPath: /run/topolvm - name: node-plugin-dir - - mountPath: /registration - name: registration-dir - - args: - - --csi-address=/run/topolvm/csi-topolvm.sock - image: '{{ .ReleaseImage.topolvm_csi_livenessprobe }}' - name: liveness-probe - resources: - requests: - cpu: 1m - memory: 7Mi - terminationMessagePolicy: FallbackToLogsOnError - volumeMounts: - - mountPath: /run/topolvm - name: node-plugin-dir - hostPID: true - initContainers: - - command: - - /usr/bin/bash - - -c - - until [ -f /etc/topolvm/lvmd.yaml ]; do echo waiting for lvmd config file; - sleep 5; done - image: '{{ .ReleaseImage.openssl }}' - name: file-checker - resources: {} - terminationMessagePolicy: FallbackToLogsOnError - volumeMounts: - - mountPath: /etc/topolvm - name: lvmd-config-dir - serviceAccountName: topolvm-node - volumes: - - hostPath: - path: /var/lib/kubelet/plugins_registry/ - type: Directory - name: registration-dir - - hostPath: - path: /var/lib/kubelet/plugins/topolvm.io/node - type: DirectoryOrCreate - name: node-plugin-dir - - hostPath: - path: /var/lib/kubelet/plugins/kubernetes.io/csi - type: DirectoryOrCreate - name: csi-plugin-dir - - hostPath: - path: /var/lib/kubelet/pods/ - type: DirectoryOrCreate - name: pod-volumes-dir - - configMap: - items: - - key: lvmd.yaml - path: lvmd.yaml - name: lvmd - name: lvmd-config-dir - updateStrategy: - type: RollingUpdate diff --git a/assets/components/lvms/vg-manager-metrics-service_v1_service.yaml b/assets/components/lvms/vg-manager-metrics-service_v1_service.yaml new file mode 100644 index 00000000000..09377dc9893 --- /dev/null +++ b/assets/components/lvms/vg-manager-metrics-service_v1_service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + service.beta.openshift.io/serving-cert-secret-name: vg-manager-metrics-cert + creationTimestamp: null + labels: + app.kubernetes.io/compose: metrics + app.kubernetes.io/name: vg-manager + name: vg-manager-metrics-service + namespace: openshift-storage +spec: + ports: + - name: vg-manager-https + port: 443 + protocol: TCP + targetPort: 8443 + selector: + app.kubernetes.io/name: vg-manager +status: + loadBalancer: {} diff --git a/assets/components/lvms/topolvm-node_rbac.authorization.k8s.io_v1_clusterrole.yaml b/assets/components/lvms/vg-manager_rbac.authorization.k8s.io_v1_clusterrole.yaml similarity index 97% rename from assets/components/lvms/topolvm-node_rbac.authorization.k8s.io_v1_clusterrole.yaml rename to assets/components/lvms/vg-manager_rbac.authorization.k8s.io_v1_clusterrole.yaml index 8e3496d575f..5ab6831e8c0 100644 --- a/assets/components/lvms/topolvm-node_rbac.authorization.k8s.io_v1_clusterrole.yaml +++ b/assets/components/lvms/vg-manager_rbac.authorization.k8s.io_v1_clusterrole.yaml @@ -1,4 +1,16 @@ rules: + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create - apiGroups: - "" resources: @@ -30,19 +42,7 @@ rules: - get - list - watch - - 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: - name: topolvm-node + name: vg-manager diff --git a/assets/components/lvms/topolvm-node_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml b/assets/components/lvms/vg-manager_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml similarity index 76% rename from assets/components/lvms/topolvm-node_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml rename to assets/components/lvms/vg-manager_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml index f2a02d5c7fe..20822de4474 100644 --- a/assets/components/lvms/topolvm-node_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml +++ b/assets/components/lvms/vg-manager_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml @@ -1,12 +1,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: topolvm-node + name: vg-manager roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: topolvm-node + name: vg-manager subjects: - kind: ServiceAccount - name: topolvm-node + name: vg-manager namespace: openshift-storage diff --git a/assets/components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_role.yaml b/assets/components/lvms/vg-manager_rbac.authorization.k8s.io_v1_role.yaml similarity index 60% rename from assets/components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_role.yaml rename to assets/components/lvms/vg-manager_rbac.authorization.k8s.io_v1_role.yaml index a0017032c8a..2b8abe81296 100644 --- a/assets/components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_role.yaml +++ b/assets/components/lvms/vg-manager_rbac.authorization.k8s.io_v1_role.yaml @@ -1,64 +1,58 @@ rules: - apiGroups: - - coordination.k8s.io + - lvm.topolvm.io + - apps resources: - - leases + - lvmvolumegroups + - daemonsets verbs: + - create + - delete - get - - watch - list - - delete + - patch - update - - create + - watch - apiGroups: - - storage.k8s.io + - lvm.topolvm.io resources: - - csistoragecapacities + - lvmvolumegroups/finalizers verbs: - - get - - list - - watch - - create - update - - patch - - delete - apiGroups: - - "" + - lvm.topolvm.io resources: - - pods + - lvmvolumegroups/status verbs: - get + - patch + - update - apiGroups: - - apps + - lvm.topolvm.io resources: - - replicasets + - lvmvolumegroupnodestatuses verbs: + - create + - delete - get + - list + - patch + - update + - watch - apiGroups: - - coordination.k8s.io + - lvm.topolvm.io resources: - - leases + - lvmvolumegroupnodestatuses/finalizers verbs: - - get - - watch - - list - - delete - update - - create - apiGroups: - - "" - - coordination.k8s.io + - lvm.topolvm.io resources: - - configmaps - - leases + - lvmvolumegroupnodestatuses/status verbs: - get - - list - - watch - - create - - update - patch - - delete + - update - apiGroups: - "" resources: @@ -66,8 +60,9 @@ rules: verbs: - create - patch + - update apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: - name: topolvm-controller + name: vg-manager namespace: openshift-storage diff --git a/assets/components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml b/assets/components/lvms/vg-manager_rbac.authorization.k8s.io_v1_rolebinding.yaml similarity index 51% rename from assets/components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml rename to assets/components/lvms/vg-manager_rbac.authorization.k8s.io_v1_rolebinding.yaml index 92c8d190a52..653ab8ef74f 100644 --- a/assets/components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml +++ b/assets/components/lvms/vg-manager_rbac.authorization.k8s.io_v1_rolebinding.yaml @@ -1,12 +1,14 @@ apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding +kind: RoleBinding metadata: - name: topolvm-controller + name: vg-manager + namespace: openshift-storage roleRef: apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: topolvm-controller + kind: Role + name: vg-manager + namespace: openshift-storage subjects: - kind: ServiceAccount - name: topolvm-controller + name: vg-manager namespace: openshift-storage diff --git a/assets/components/lvms/topolvm-node_v1_serviceaccount.yaml b/assets/components/lvms/vg-manager_v1_serviceaccount.yaml similarity index 83% rename from assets/components/lvms/topolvm-node_v1_serviceaccount.yaml rename to assets/components/lvms/vg-manager_v1_serviceaccount.yaml index f3f514b7da8..638af5bd262 100644 --- a/assets/components/lvms/topolvm-node_v1_serviceaccount.yaml +++ b/assets/components/lvms/vg-manager_v1_serviceaccount.yaml @@ -2,5 +2,5 @@ apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: null - name: topolvm-node + name: vg-manager namespace: openshift-storage diff --git a/assets/release/release-aarch64.json b/assets/release/release-aarch64.json index 11b4d39ef8b..dd33c6a2637 100644 --- a/assets/release/release-aarch64.json +++ b/assets/release/release-aarch64.json @@ -11,11 +11,7 @@ "ovn-kubernetes-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:4ef113223a70ed1ef3d2fe260d07868a37a0a31d96f99e2150cc6675c5e5aadd", "pod": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:0dad79eca25c92d00bf123571267885992f80885a4e47d22112e26cf0d2c8f3e", "service-ca-operator": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:c239885606463c7dc49f0f0b3d144007fbfa0b3ef4a58a58cd920c36d9b32e4a", - "topolvm_csi": "registry.redhat.io/lvms4/topolvm-rhel9@sha256:ce0c78c2867fb0b73c4911ae6afd5aaf9a413480cfcf4f31f46f2387c3df97e0", - "topolvm_csi_registrar": "registry.redhat.io/openshift4/ose-csi-node-driver-registrar@sha256:95691c21198e20d11777d592806fa00c018c17443d9b3aee853891dac6090470", - "topolvm_csi_livenessprobe": "registry.redhat.io/openshift4/ose-csi-livenessprobe@sha256:98ad03919da81c910aaa8a4f12fcae3048f2119735aeb7ca5271f7c16cf5e4e6", - "topolvm_csi_resizer": "registry.redhat.io/openshift4/ose-csi-external-resizer@sha256:94f4a9ad37891cfbf58ca7db58000e703ff4d9d7a7b207d50ec844c1610e2111", - "topolvm_csi_provisioner": "registry.redhat.io/openshift4/ose-csi-external-provisioner@sha256:76a5646d4b8406ae9065a1605644ec641acc97aa471ebae744e8e06487cec765", + "lvms_operator": "registry.redhat.io/lvms4/lvms-rhel9-operator@sha256:9c2a0c3d0c711e20f566f528498e2df4b7163174ac5f249d0646b3a04ad8ea72", "csi-external-snapshotter": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f0ea816d2f738e44d561295b30727857388a026cf25175770d4fc668e8963c56", "csi-snapshot-controller": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:7fb1800201cb821f6ec397abc67e63c105faba8c79d967ff10d0beddd4bb01fd", "csi-snapshot-validation-webhook": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:326c222e4ff6f497f83d05b5cc75e539f8333c60b8bf822fa7c7c56532bec5a8" diff --git a/assets/release/release-x86_64.json b/assets/release/release-x86_64.json index 6462c14ed75..a01fcb76a9d 100644 --- a/assets/release/release-x86_64.json +++ b/assets/release/release-x86_64.json @@ -11,11 +11,7 @@ "ovn-kubernetes-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:04f445e037af9a314307a6af7d7e3f0b634dcb09b9ccdbb341c0b13c9db1ab8e", "pod": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:566bf08daa0f3536090027e870383da6ac2d09ae3c9c516fb2e20dc515bff021", "service-ca-operator": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:40f7953f07715c04755720b8c2112be3bf079d506008ab53b7472e4a651375a8", - "topolvm_csi": "registry.redhat.io/lvms4/topolvm-rhel9@sha256:ce0c78c2867fb0b73c4911ae6afd5aaf9a413480cfcf4f31f46f2387c3df97e0", - "topolvm_csi_registrar": "registry.redhat.io/openshift4/ose-csi-node-driver-registrar@sha256:95691c21198e20d11777d592806fa00c018c17443d9b3aee853891dac6090470", - "topolvm_csi_livenessprobe": "registry.redhat.io/openshift4/ose-csi-livenessprobe@sha256:98ad03919da81c910aaa8a4f12fcae3048f2119735aeb7ca5271f7c16cf5e4e6", - "topolvm_csi_resizer": "registry.redhat.io/openshift4/ose-csi-external-resizer@sha256:94f4a9ad37891cfbf58ca7db58000e703ff4d9d7a7b207d50ec844c1610e2111", - "topolvm_csi_provisioner": "registry.redhat.io/openshift4/ose-csi-external-provisioner@sha256:76a5646d4b8406ae9065a1605644ec641acc97aa471ebae744e8e06487cec765", + "lvms_operator": "registry.redhat.io/lvms4/lvms-rhel9-operator@sha256:9c2a0c3d0c711e20f566f528498e2df4b7163174ac5f249d0646b3a04ad8ea72", "csi-external-snapshotter": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1f16a7104e080e0b1a4e224df4c645a988534e219387ab37a6b8ab6958aa9ae2", "csi-snapshot-controller": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:d552cb424a00d65c3f08725bffb9001b2ace10ba4c10bb5484c13d78d2751ef6", "csi-snapshot-validation-webhook": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1277525b951258ad8101613b0a7f8332258fdf3b10103bc76fb1bb5f84e780f0" diff --git a/pkg/assets/admission-registration.go b/pkg/assets/admission-registration.go index a1fe262f7c7..f8631874c93 100644 --- a/pkg/assets/admission-registration.go +++ b/pkg/assets/admission-registration.go @@ -45,7 +45,7 @@ func (v *validationWebhookCfg) Handle(ctx context.Context) error { func admissionRegistrationClient(kubeconfigPath string) *arClientV1.AdmissionregistrationV1Client { restConfig, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath) if err != nil { - klog.Fatalf("failed to create admission-registration client: %v", err) + klog.Fatalf("failed to create admission-registration Client: %v", err) } return arClientV1.NewForConfigOrDie(rest.AddUserAgent(restConfig, "admission-registration")) } diff --git a/pkg/assets/crd.go b/pkg/assets/crd.go index fd671ed2e34..55e5cd61dba 100644 --- a/pkg/assets/crd.go +++ b/pkg/assets/crd.go @@ -15,7 +15,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" - klog "k8s.io/klog/v2" + "k8s.io/klog/v2" "github.com/openshift/library-go/pkg/operator/resource/resourceapply" "github.com/openshift/microshift/pkg/config" @@ -38,6 +38,9 @@ var ( "crd/route.crd.yaml", "crd/storage_version_migration.crd.yaml", "components/lvms/topolvm.io_logicalvolumes.yaml", + "components/lvms/lvm.topolvm.io_lvmclusters.yaml", + "components/lvms/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml", + "components/lvms/lvm.topolvm.io_lvmvolumegroups.yaml", "components/csi-snapshot-controller/volumesnapshotclasses.yaml", "components/csi-snapshot-controller/volumesnapshotcontents.yaml", "components/csi-snapshot-controller/volumesnapshots.yaml", diff --git a/pkg/assets/storage.go b/pkg/assets/storage.go index 3a4d4d1733c..56c6cb6f371 100644 --- a/pkg/assets/storage.go +++ b/pkg/assets/storage.go @@ -90,56 +90,6 @@ func ApplyStorageClasses(ctx context.Context, scs []string, render RenderFunc, p return applySCs(ctx, scs, sc, render, params) } -type cdApplier struct { - Client *scclientv1.StorageV1Client - cd *scv1.CSIDriver -} - -func (c *cdApplier) Read(objBytes []byte, render RenderFunc, params RenderParams) { - var err error - if render != nil { - objBytes, err = render(objBytes, params) - if err != nil { - panic(err) - } - } - obj, err := runtime.Decode(scCodecs.UniversalDecoder(scv1.SchemeGroupVersion), objBytes) - if err != nil { - panic(err) - } - c.cd = obj.(*scv1.CSIDriver) -} - -func (c *cdApplier) Handle(ctx context.Context) error { - _, _, err := resourceapply.ApplyCSIDriver(ctx, c.Client, assetsEventRecorder, c.cd) - return err -} - -func ApplyCSIDrivers(ctx context.Context, drivers []string, render RenderFunc, params RenderParams, kubeconfigPath string) error { - applier := &cdApplier{} - applier.Client = scClient(kubeconfigPath) - return applyCDs(ctx, drivers, applier, render, params) -} - -func applyCDs(ctx context.Context, cds []string, handler resourceHandler, render RenderFunc, params RenderParams) error { - lock.Lock() - defer lock.Unlock() - - for _, cd := range cds { - klog.Infof("Applying csiDriver %s", cd) - objBytes, err := embedded.Asset(cd) - if err != nil { - return fmt.Errorf("error getting asset %s: %v", cd, err) - } - handler.Read(objBytes, render, params) - if err := handler.Handle(ctx); err != nil { - klog.Warningf("Failed to apply CSIDriver api %s: %v", cd, err) - return err - } - } - return nil -} - type volumeSnapshotClassApplier struct { Client dynamic.Interface vc *unstructured.Unstructured @@ -192,12 +142,12 @@ func applyVolumeSnapshotClass(ctx context.Context, handler resourceHandler, vcs return nil } -// storageDynamicClient returns a generic kubernetes client which can handle arbitrary API schemas. We use this instead of th -// volumeSnapshot client to avoid vendoring +// storageDynamicClient returns a generic kubernetes Client which can handle arbitrary API schemas. We use this instead of th +// volumeSnapshot Client to avoid vendoring func storageDynamicClient(kubeconfigPath string) *dynamic.DynamicClient { restCfg, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath) if err != nil { panic(err) } - return dynamic.NewForConfigOrDie(rest.AddUserAgent(restCfg, "storage-dynamic-client")) + return dynamic.NewForConfigOrDie(rest.AddUserAgent(restCfg, "storage-dynamic-Client")) } diff --git a/pkg/assets/unstructured.go b/pkg/assets/unstructured.go new file mode 100644 index 00000000000..6acc7d0d261 --- /dev/null +++ b/pkg/assets/unstructured.go @@ -0,0 +1,208 @@ +package assets + +import ( + "bytes" + "context" + "fmt" + "sync" + + "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" + embedded "github.com/openshift/microshift/assets" + "github.com/openshift/microshift/pkg/util" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/client-go/discovery" + "k8s.io/client-go/discovery/cached/memory" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/klog/v2" + "k8s.io/utils/ptr" +) + +// ModifyOnExists is a function that modifies the existing object based on the required object. +// The first argument is a pointer to a boolean that should be set to true if the object was modified. +// i.e. `*modified = true` +// The second argument is a pointer to the existing object on the cluster. +// The third argument is a pointer to the required object from the template. +// If Not set, the object will only have its metadata fields updated. +// If set, the object will be modified based on the function. +type ModifyOnExists func(modified *bool, existing, required *unstructured.Unstructured) + +type configClientCacheEntry struct { + base dynamic.Interface + mapper meta.ResettableRESTMapper +} + +// configClientCache is a cache of dynamic clients and REST mappers for each kubeconfig path. +// This is used to avoid creating a new client and REST mapper for each resource. +var configClientCache = make(map[string]configClientCacheEntry, 1) +var configClientCacheLock sync.RWMutex + +type unstructuredApplier struct { + base dynamic.Interface + mapper meta.ResettableRESTMapper + + Client dynamic.ResourceInterface + unstructured *unstructured.Unstructured + + // modify is a function that modifies the existing object based on the required object. + // The first argument is a pointer to a boolean that should be set to true if the object was modified. + // i.e. `*modified = true` + // The second argument is a pointer to the existing object on the cluster. + // The third argument is a pointer to the required object from the template. + // If Not set, the object will only have its metadata fields updated. + // If set, the object will be modified based on the function. + ModifyOnExists +} + +func unstructuredConfigAndClient(kubeconfigPath string) configClientCacheEntry { + configClientCacheLock.RLock() + entry, ok := configClientCache[kubeconfigPath] + configClientCacheLock.RUnlock() + if ok { + return entry + } + + restConfig, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath) + if err != nil { + panic(err) + } + restConfig = rest.AddUserAgent(restConfig, "generic-microshift-agent") + + httpClient, err := rest.HTTPClientFor(restConfig) + if err != nil { + panic(err) + } + + base, err := dynamic.NewForConfigAndClient(restConfig, httpClient) + if err != nil { + panic(err) + } + + disco, err := discovery.NewDiscoveryClientForConfigAndClient(restConfig, httpClient) + if err != nil { + panic(err) + } + + entry = configClientCacheEntry{ + base: base, + mapper: restmapper.NewDeferredDiscoveryRESTMapper(memory.NewMemCacheClient(disco)), + } + + configClientCacheLock.Lock() + configClientCache[kubeconfigPath] = entry + configClientCacheLock.Unlock() + + return entry +} + +func (d *unstructuredApplier) Read(objBytes []byte, render RenderFunc, params RenderParams) { + var err error + if render != nil { + objBytes, err = render(objBytes, params) + if err != nil { + panic(err) + } + } + + unstruct, err := util.ConvertYAMLOrJSONToUnstructured(bytes.NewReader(objBytes)) + if err != nil { + panic(fmt.Errorf("failed to parse LVMCluster: %w", err)) + } + + d.unstructured = unstruct + + gvk := d.unstructured.GroupVersionKind() + mapping, err := d.mapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + panic(fmt.Errorf("failed to get RESTMapping for %s: %w", unstruct.GetObjectKind(), err)) + } + d.unstructured.SetGroupVersionKind(mapping.GroupVersionKind) + + if d.unstructured.GetNamespace() != "" { + d.Client = d.base.Resource(mapping.Resource).Namespace(d.unstructured.GetNamespace()) + } else { + d.Client = d.base.Resource(mapping.Resource) + } +} + +func (d *unstructuredApplier) Handle(ctx context.Context) error { + existing, err := d.Client.Get(ctx, d.unstructured.GetName(), metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + if _, err := d.Client.Create(ctx, d.unstructured, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("failed to create %s: %w", d.unstructured.GroupVersionKind(), err) + } + klog.Infof("Created %s: %s", d.unstructured.GroupVersionKind(), d.unstructured.GetName()) + return nil + } + if err != nil { + return fmt.Errorf("failed to verify existance of %s: %w", d.unstructured.GroupVersionKind(), err) + } + + var modified bool + + if d.ModifyOnExists != nil { + d.ModifyOnExists(&modified, existing, d.unstructured) + } + + // replicate resourcemerge.EnsureObjectMeta + // this is a bit of a hack, but it's the only way to get the same behavior as resourceMerge + resourcemerge.SetStringIfSet(&modified, ptr.To(existing.GetNamespace()), d.unstructured.GetNamespace()) + resourcemerge.SetStringIfSet(&modified, ptr.To(existing.GetName()), d.unstructured.GetName()) + resourcemerge.MergeMap(&modified, ptr.To(existing.GetLabels()), d.unstructured.GetLabels()) + resourcemerge.MergeMap(&modified, ptr.To(existing.GetAnnotations()), d.unstructured.GetAnnotations()) + resourcemerge.MergeOwnerRefs(&modified, ptr.To(existing.GetOwnerReferences()), d.unstructured.GetOwnerReferences()) + + if !modified { + return nil + } + + if _, err = d.Client.Update(ctx, existing, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("failed to update %s: %w", d.unstructured.GroupVersionKind(), err) + } + + klog.Infof("Updated %s: %s", d.unstructured.GroupVersionKind(), d.unstructured.GetName()) + + return nil +} + +func applyGeneric(ctx context.Context, resources []string, handler resourceHandler, render RenderFunc, params RenderParams) error { + lock.Lock() + defer lock.Unlock() + + for _, resource := range resources { + klog.Infof("Applying resource %s", resource) + objBytes, err := embedded.Asset(resource) + if err != nil { + return fmt.Errorf("error getting asset %s: %v", resource, err) + } + handler.Read(objBytes, render, params) + if err := handler.Handle(ctx); err != nil { + klog.Warningf("Failed to apply resource %s: %v", resource, err) + return err + } + } + + return nil +} + +func ApplyGeneric( + ctx context.Context, + resources []string, + render RenderFunc, + params RenderParams, + modify ModifyOnExists, + kubeconfigPath string, +) error { + configAndClient := unstructuredConfigAndClient(kubeconfigPath) + applier := &unstructuredApplier{ + base: configAndClient.base, + mapper: configAndClient.mapper, + ModifyOnExists: modify, + } + return applyGeneric(ctx, resources, applier, render, params) +} diff --git a/pkg/assets/unstructured_test.go b/pkg/assets/unstructured_test.go new file mode 100644 index 00000000000..67abcb840ba --- /dev/null +++ b/pkg/assets/unstructured_test.go @@ -0,0 +1,22 @@ +package assets + +import ( + "context" + "testing" +) + +func TestApply(t *testing.T) { + + err := ApplyGeneric(context.Background(), + []string{ + "components/lvms/lvms_default-lvmcluster.yaml", + }, + nil, + map[string]interface{}{}, + nil, + "/home/jmoller/Projects/microshift/kubeconfig") + + if err != nil { + t.Errorf("Failed to apply lvmcluster: %v", err) + } +} diff --git a/pkg/components/render.go b/pkg/components/render.go index 4f5f83f1926..4b48bfae719 100755 --- a/pkg/components/render.go +++ b/pkg/components/render.go @@ -7,11 +7,8 @@ import ( "path/filepath" "text/template" - "sigs.k8s.io/yaml" - "github.com/openshift/microshift/pkg/assets" "github.com/openshift/microshift/pkg/config" - "github.com/openshift/microshift/pkg/config/lvmd" "github.com/openshift/microshift/pkg/release" ) @@ -47,18 +44,3 @@ func renderTemplate(tb []byte, data assets.RenderParams) ([]byte, error) { } return buf.Bytes(), nil } - -func renderLvmdParams(l *lvmd.Lvmd) (assets.RenderParams, error) { - r := make(assets.RenderParams) - b, err := yaml.Marshal(l) - if err != nil { - return nil, err - } - content := string(b) - if l.Message != "" { - content = fmt.Sprintf("# %s\n%s", l.Message, content) - } - r["lvmd"] = content - r["SocketName"] = l.SocketName - return r, nil -} diff --git a/pkg/components/storage.go b/pkg/components/storage.go index 8cd4c290af9..9c0c5f7e323 100644 --- a/pkg/components/storage.go +++ b/pkg/components/storage.go @@ -3,9 +3,9 @@ package components import ( "context" "errors" - "fmt" "os" "path/filepath" + "sync" "k8s.io/klog/v2" @@ -14,89 +14,110 @@ import ( "github.com/openshift/microshift/pkg/config/lvmd" ) -// getCSIPluginConfig searches for a user-defined lvmd configuration file in /etc/microshift. If found, returns -// the lvmd config. If not found, returns a default-value lvmd config. If an unmarshalling errors, returns nil -// and the error. -func getCSIPluginConfig() (*lvmd.Lvmd, error) { - lvmdConfig := filepath.Join(filepath.Dir(config.ConfigFile), lvmd.LvmdConfigFileName) - if _, err := os.Stat(lvmdConfig); !errors.Is(err, os.ErrNotExist) { - return lvmd.NewLvmdConfigFromFile(lvmdConfig) - } - return lvmd.DefaultLvmdConfig() +var lvmdConfigPathInMicroShift string +var lvmdConfigPathInMicroShiftSync sync.Once + +func lvmdConfigForMicroShift() string { + lvmdConfigPathInMicroShiftSync.Do(func() { + lvmdConfigPathInMicroShift = filepath.Join(filepath.Dir(config.ConfigFile), lvmd.LvmdConfigFileName) + }) + return lvmdConfigPathInMicroShift +} + +// loadCSIPluginConfig searches for a user-defined lvmd configuration file in /etc/microshift. If found, returns +// the lvmd config. If not found, returns a default-value lvmd config which is saved in /etc/microshift. +func loadCSIPluginConfig() (*lvmd.Lvmd, error) { + microshiftPath := lvmdConfigForMicroShift() + _, err := os.Stat(microshiftPath) + + var config *lvmd.Lvmd + if errors.Is(err, os.ErrNotExist) { + if config, err = lvmd.DefaultLvmdConfig(); err != nil { + return nil, err + } + if err := lvmd.SaveLvmdConfigToFile(config, microshiftPath); err != nil { + return nil, err + } + } else if err != nil { + return nil, err + } else { + config, err = lvmd.NewLvmdConfigFromFile(microshiftPath) + if err != nil { + return nil, err + } + } + + return config, nil } func startCSIPlugin(ctx context.Context, cfg *config.Config, kubeconfigPath string) error { + if err := lvmd.LvmPresentOnMachine(); err != nil { + klog.Warningf("skipping CSI deployment: %v", err) + return nil + } + + // the lvmd file should be located in the same directory as the microshift config to minimize coupling with the + // csi plugin. + lvmdCfg, err := loadCSIPluginConfig() + if err != nil { + return err + } + if !lvmdCfg.IsEnabled() { + klog.V(2).Infof("CSI is disabled. %s", lvmdCfg.Message) + return nil + } + var ( + // CRDS are handled in ns = []string{ "components/lvms/topolvm-openshift-storage_namespace.yaml", } sa = []string{ - "components/lvms/topolvm-node_v1_serviceaccount.yaml", - "components/lvms/topolvm-controller_v1_serviceaccount.yaml", + "components/lvms/lvms-operator_v1_serviceaccount.yaml", + "components/lvms/vg-manager_v1_serviceaccount.yaml", } role = []string{ - "components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_role.yaml", + "components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_role.yaml", + "components/lvms/vg-manager_rbac.authorization.k8s.io_v1_role.yaml", + "components/lvms/lvms-metrics_rbac.authorization.k8s.io_v1_role.yaml", } rb = []string{ - "components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_rolebinding.yaml", + "components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_rolebinding.yaml", + "components/lvms/vg-manager_rbac.authorization.k8s.io_v1_rolebinding.yaml", + "components/lvms/lvms-metrics_rbac.authorization.k8s.io_v1_rolebinding.yaml", } cr = []string{ - "components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_clusterrole.yaml", - "components/lvms/topolvm-node-scc_rbac.authorization.k8s.io_v1_clusterrole.yaml", - "components/lvms/topolvm-node_rbac.authorization.k8s.io_v1_clusterrole.yaml", + "components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_clusterrole.yaml", + "components/lvms/vg-manager_rbac.authorization.k8s.io_v1_clusterrole.yaml", } crb = []string{ - "components/lvms/topolvm-controller_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml", - "components/lvms/topolvm-node-scc_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml", - "components/lvms/topolvm-node_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml", - } - cd = []string{ - "components/lvms/csi-driver.yaml", + "components/lvms/lvms-operator_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml", + "components/lvms/vg-manager_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml", } - cm = "components/lvms/topolvm-lvmd-config_configmap_v1.yaml" cm_ver = "components/lvms/topolvm-configmap_lvms-version.yaml" - ds = []string{ - "components/lvms/topolvm-node_daemonset.yaml", - } deploy = []string{ - "components/lvms/topolvm-controller_deployment.yaml", + "components/lvms/lvms-operator_apps_v1_deployment.yaml", + } + lvmClusters = []string{ + "components/lvms/lvms_default-lvmcluster.yaml", } sc = []string{ "components/lvms/topolvm_default-storage-class.yaml", } - scc = []string{ - "components/lvms/topolvm-node-securitycontextconstraint.yaml", + svc = []string{ + "components/lvms/lvms-webhook-service_v1_service.yaml", + "components/lvms/lvms-operator-metrics-service_v1_service.yaml", + "components/lvms/vg-manager-metrics-service_v1_service.yaml", + } + vwc = []string{ + "components/lvms/lvms-operator_admissionregistration.k8s.io_v1_webhook.yaml", } ) - if err := lvmd.LvmSupported(); err != nil { - klog.Warningf("skipping CSI deployment: %v", err) - return nil - } - - // the lvmd file should be located in the same directory as the microshift config to minimize coupling with the - // csi plugin. - lvmdCfg, err := getCSIPluginConfig() - if err != nil { - return err - } - if !lvmdCfg.IsEnabled() { - klog.V(2).Infof("CSI is disabled. %s", lvmdCfg.Message) - return nil - } - lvmdRenderParams, err := renderLvmdParams(lvmdCfg) - if err != nil { - return fmt.Errorf("rendering lvmd params: %v", err) - } - if err := assets.ApplyStorageClasses(ctx, sc, nil, nil, kubeconfigPath); err != nil { klog.Warningf("Failed to apply storage cass %v: %v", sc, err) return err } - if err := assets.ApplyCSIDrivers(ctx, cd, nil, nil, kubeconfigPath); err != nil { - klog.Warningf("Failed to apply csiDriver %v: %v", sc, err) - return err - } if err := assets.ApplyNamespaces(ctx, ns, kubeconfigPath); err != nil { klog.Warningf("Failed to apply ns %v: %v", ns, err) return err @@ -121,25 +142,26 @@ func startCSIPlugin(ctx context.Context, cfg *config.Config, kubeconfigPath stri klog.Warningf("Failed to apply clusterrolebinding %v: %v", crb, err) return err } - if err := assets.ApplyConfigMapWithData(ctx, cm, map[string]string{"lvmd.yaml": lvmdRenderParams["lvmd"].(string)}, kubeconfigPath); err != nil { + if err := assets.ApplyConfigMaps(ctx, []string{cm_ver}, nil, nil, kubeconfigPath); err != nil { klog.Warningf("Failed to apply configMap %v: %v", crb, err) return err } - if err := assets.ApplyConfigMaps(ctx, []string{cm_ver}, nil, nil, kubeconfigPath); err != nil { - klog.Warningf("Failed to apply configMap %v: %v", crb, err) + if err := assets.ApplyServices(ctx, svc, nil, map[string]interface{}{}, kubeconfigPath); err != nil { + klog.Warningf("Failed to apply service %v: %v", svc, err) return err } if err := assets.ApplyDeployments(ctx, deploy, renderTemplate, renderParamsFromConfig(cfg, nil), kubeconfigPath); err != nil { klog.Warningf("Failed to apply deployment %v: %v", deploy, err) return err } - if err := assets.ApplyDaemonSets(ctx, ds, renderTemplate, renderParamsFromConfig(cfg, lvmdRenderParams), kubeconfigPath); err != nil { - klog.Warningf("Failed to apply daemonsets %v: %v", ds, err) + if err := assets.ApplyValidatingWebhookConfiguration(ctx, vwc, kubeconfigPath); err != nil { + klog.Warningf("Failed to apply validating webhook configuration %v: %v", vwc, err) return err } - if err := assets.ApplySCCs(ctx, scc, nil, nil, kubeconfigPath); err != nil { - klog.Warningf("Failed to apply sccs %v: %v", scc, err) + if err := assets.ApplyGeneric(ctx, lvmClusters, nil, map[string]interface{}{}, nil, kubeconfigPath); err != nil { + klog.Warningf("Failed to apply lvmcluster: %v", err) return err } + return nil } diff --git a/pkg/config/lvmd/lvmd.go b/pkg/config/lvmd/lvmd.go index 19ac344a072..ceebd63d197 100644 --- a/pkg/config/lvmd/lvmd.go +++ b/pkg/config/lvmd/lvmd.go @@ -133,8 +133,20 @@ func NewLvmdConfigFromFile(p string) (*Lvmd, error) { return l, nil } -func LvmSupported() error { - if _, err := exec.LookPath("vgs"); err != nil { +func SaveLvmdConfigToFile(l *Lvmd, p string) error { + buf, err := yaml.Marshal(l) + if err != nil { + return fmt.Errorf("marshalling lvmd config: %v", err) + } + err = os.WriteFile(p, buf, 0644) + if err != nil { + return fmt.Errorf("writing lvmd config: %v", err) + } + return nil +} + +func LvmPresentOnMachine() error { + if _, err := exec.LookPath("lvm"); err != nil { return fmt.Errorf("failed to find 'vgs' command line tool: %v", err) } return nil diff --git a/pkg/util/unstructured.go b/pkg/util/unstructured.go new file mode 100644 index 00000000000..1a44027b8d1 --- /dev/null +++ b/pkg/util/unstructured.go @@ -0,0 +1,65 @@ +package util + +import ( + "fmt" + "io" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/client-go/discovery" + "k8s.io/client-go/discovery/cached/memory" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" +) + +// ConvertYAMLOrJSONToUnstructured converts a YAML or JSON stream to an unstructured object. +// It returns an error if the stream cannot be decoded or the object cannot be converted to unstructured. +// The function is used to parse Kubernetes resources from files that are unknown at compile time. +func ConvertYAMLOrJSONToUnstructured(reader io.Reader) (*unstructured.Unstructured, error) { + raw := map[string]interface{}{} + + if err := yaml.NewYAMLOrJSONDecoder(reader, 0 /* no support for JSON streams */).Decode(&raw); err != nil { + return nil, fmt.Errorf("failed to decode object: %w", err) + } + + unstruct := unstructured.Unstructured{} + + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(raw, &unstruct); err != nil { + return nil, fmt.Errorf("failed to convert object to unstructured: %w", err) + } + + return &unstruct, nil +} + +func ClientForDynamicObjectKind(config *rest.Config, object schema.ObjectKind) (dynamic.NamespaceableResourceInterface, error) { + gvk := object.GroupVersionKind() + + httpClient, err := rest.HTTPClientFor(config) + if err != nil { + return nil, err + } + + clnt, err := dynamic.NewForConfigAndClient(config, httpClient) + if err != nil { + return nil, err + } + + disco, err := discovery.NewDiscoveryClientForConfigAndClient(config, httpClient) + if err != nil { + return nil, err + } + + mapper := restmapper.NewDeferredDiscoveryRESTMapper(memory.NewMemCacheClient(disco)) + + mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + return nil, err + } + + object.SetGroupVersionKind(mapping.GroupVersionKind) + + return clnt.Resource(mapping.Resource), nil +} diff --git a/scripts/auto-rebase/last_lvms_rebase.sh b/scripts/auto-rebase/last_lvms_rebase.sh index 816765c828e..32ccc081690 100755 --- a/scripts/auto-rebase/last_lvms_rebase.sh +++ b/scripts/auto-rebase/last_lvms_rebase.sh @@ -1,2 +1,2 @@ #!/bin/bash -x -./scripts/auto-rebase/rebase-lvms.sh to "registry.redhat.io/lvms4/lvms-operator-bundle:v4.15.0" +./scripts/auto-rebase/rebase-lvms.sh to "registry-proxy.engineering.redhat.com/rh-osbs/lvms4-lvms-operator-bundle:v4.16.0-58" diff --git a/scripts/auto-rebase/lvms_assets.yaml b/scripts/auto-rebase/lvms_assets.yaml index 3d6458c4bd0..3e744549dd6 100644 --- a/scripts/auto-rebase/lvms_assets.yaml +++ b/scripts/auto-rebase/lvms_assets.yaml @@ -4,31 +4,40 @@ assets: src: lvms/amd64/ no_clean: True files: + # Version Config Map - file: topolvm-configmap_lvms-version.yaml - - file: topolvm-controller_rbac.authorization.k8s.io_v1_clusterrole.yaml - - file: topolvm-controller_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml - - file: topolvm-controller_rbac.authorization.k8s.io_v1_role.yaml - - file: topolvm-controller_rbac.authorization.k8s.io_v1_rolebinding.yaml - - file: topolvm-controller_v1_serviceaccount.yaml - - file: topolvm-node_rbac.authorization.k8s.io_v1_clusterrole.yaml - - file: topolvm-node_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml - - file: topolvm-node_v1_serviceaccount.yaml + # CRDs - file: topolvm.io_logicalvolumes.yaml - - file: topolvm-node-scc_rbac.authorization.k8s.io_v1_clusterrole.yaml - ignore: "provided by MicroShift" - - file: topolvm-node-scc_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml - ignore: "provided by MicroShift" - - file: csi-driver.yaml - ignore: "provided by MicroShift" - - file: topolvm-controller_deployment.yaml - ignore: "provided by MicroShift" - - file: topolvm-lvmd-config_configmap_v1.yaml - ignore: "provided by MicroShift" - - file: topolvm-node_daemonset.yaml - ignore: "provided by MicroShift" - - file: topolvm-node-securitycontextconstraint.yaml - ignore: "provided by MicroShift" + - file: lvm.topolvm.io_lvmclusters.yaml + - file: lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml + - file: lvm.topolvm.io_lvmvolumegroups.yaml + # Extracted CSV RBAC Information + - file: lvms-operator_rbac.authorization.k8s.io_v1_clusterrole.yaml + - file: lvms-operator_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml + - file: lvms-operator_rbac.authorization.k8s.io_v1_role.yaml + - file: lvms-operator_rbac.authorization.k8s.io_v1_rolebinding.yaml + - file: lvms-metrics_rbac.authorization.k8s.io_v1_role.yaml + - file: lvms-metrics_rbac.authorization.k8s.io_v1_rolebinding.yaml + - file: vg-manager_rbac.authorization.k8s.io_v1_clusterrole.yaml + - file: vg-manager_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml + - file: vg-manager_rbac.authorization.k8s.io_v1_role.yaml + - file: vg-manager_rbac.authorization.k8s.io_v1_rolebinding.yaml + # Services + - file: lvms-operator_v1_serviceaccount.yaml + - file: vg-manager_v1_serviceaccount.yaml + - file: lvms-webhook-service_v1_service.yaml + - file: lvms-operator-metrics-service_v1_service.yaml + - file: vg-manager-metrics-service_v1_service.yaml + # Deployment + - file: lvms-operator_apps_v1_deployment.yaml + # Webhook + - file: lvms-operator_admissionregistration.k8s.io_v1_webhook.yaml + # Manual Namespace instead of OLM one - file: topolvm-openshift-storage_namespace.yaml ignore: "provided by MicroShift" + # Manual Storage Class instead of automatic LVMCluster creation - file: topolvm_default-storage-class.yaml ignore: "provided by MicroShift" + # LVMCluster instead of User-created LVMCluster + - file: lvms_default-lvmcluster.yaml + ignore: "provided by MicroShift" diff --git a/scripts/auto-rebase/rebase-lvms.sh b/scripts/auto-rebase/rebase-lvms.sh index a59c67e4ea7..d10cdd382a1 100755 --- a/scripts/auto-rebase/rebase-lvms.sh +++ b/scripts/auto-rebase/rebase-lvms.sh @@ -153,15 +153,42 @@ download_lvms_operator_bundle_manifest(){ local csv="lvms-operator.clusterserviceversion.yaml" local namespace="openshift-storage" extract_lvms_rbac_from_cluster_service_version "${PWD}" "${csv}" "${namespace}" + extract_lvms_deploy_from_cluster_service_version "${PWD}" "${csv}" "${namespace}" # Push the configMap to the kube-public namespace so that it is available to all users/apps generate_version_config_map "${version}" "lvms-version" "kube-public"\ > "${PWD}/topolvm-configmap_lvms-version.yaml" + # Loop over all services and roles since they need to be patched with a namespace if they were not + # part of the CSV role definitions + for file in ${PWD}/*; do + if [[ $file == *.yaml || $file == *.yml ]]; then + patch_namespace "Service" "$file" "$namespace" + patch_namespace "Role" "$file" "$namespace" + patch_namespace "RoleBinding" "$file" "$namespace" + fi + done + popd || return 1 done } +patch_namespace() { + local kind=$1 + local file=$2 + local namespace=$3 + + if [[ $(yq e ".kind == \"${kind}\"" "$file") == "true" ]]; then + # Check if the .metadata.namespace is not set or empty + if [[ $(yq e ".metadata.namespace == \"${namespace}\"" "$file") == "false" ]]; then + echo "patching .metadata.namespace to \"${namespace}\" in $file" + # Set the .metadata.namespace to the specified value + yq e '.metadata.namespace = "'${namespace}'"' -i "$file" + fi + fi +} + + write_lvms_images_for_arch(){ local arch="$1" arch_dir="${STAGING_DIR}/lvms/${arch}" @@ -171,11 +198,7 @@ write_lvms_images_for_arch(){ } declare -a include_images=( - "topolvm-csi" - "topolvm-csi-provisioner" - "topolvm-csi-resizer" - "topolvm-csi-registrar" - "topolvm-csi-livenessprobe" + "lvms-operator" ) local csv_manifest="${arch_dir}/lvms-operator.clusterserviceversion.yaml" @@ -294,6 +317,87 @@ extract_lvms_rbac_from_cluster_service_version() { done } +extract_lvms_deploy_from_cluster_service_version() { + local dest="$1" + local csv="$2" + local namespace="$3" + + title "extracting lvms clusterserviceversion.yaml into separate Deployments" + + local deployments=($(yq eval '.spec.install.spec.deployments[].name' < "${csv}")) + + for deployment in "${deployments[@]}"; do + echo "extracting bundle .spec.install.spec.deployments by name ${deployment}" + + local deployment_file="${dest}/${deployment}_apps_v1_deployment.yaml" + echo "generating ${deployment_file}" + yq eval ".spec.install.spec.deployments[] | select(.name == \"${deployment}\") | + .apiVersion = \"apps/v1\" | + .kind = \"Deployment\" | + .metadata.namespace = \"${namespace}\" | + .metadata.name = .name | + del(.name) + " "${csv}" > "${deployment_file}" + + + echo "extracting webhook .spec.install.spec.webhookdefinitions by deployment ${deployment}" + + # This assumes that we have only one webhook per deployment, if we get more this needs to be adjusted! + # The assumptions this rebase script makes are + # - One webhook defined per deployment + # - The webhook name can be uniquely defined by .generateName + .deploymentName (derived from above) + # - One object per webhook type + # - webhook available under service "lvms-webhook-service" (hardcoded in bundle, could also be generated) + local webhook_file="${dest}/${deployment}_admissionregistration.k8s.io_v1_webhook.yaml" + deployment=${deployment} namespace=${namespace} yq eval ' + .spec.webhookdefinitions[] + | select(.deploymentName == env(deployment)) + | .apiVersion = "admissionregistration.k8s.io/v1" + | with(select(.type == "ValidatingAdmissionWebhook"); .kind = "ValidatingWebhookConfiguration" ) + | with(select(.type == "MutatingAdmissionWebhook"); .kind = "MutatingWebhookConfiguration" ) | del(.type) + | .metadata.namespace = env(namespace) + | .metadata.name = .generateName + "-" + .deploymentName + | .metadata.annotations."service.beta.openshift.io/inject-cabundle" = "true" + | del(.targetPort) + | .webhooks[0] = { + "name": .generateName, + "clientConfig": {"service": { + "name": "lvms-webhook-service", + "namespace": env(namespace), + "path": .webhookPath, + "port": .containerPort + }}, + "rules": .rules | map(. + {"scope": "*"}), + "failurePolicy": .failurePolicy, + "matchPolicy": "Equivalent", + "sideEffects": .sideEffects, + "timeoutSeconds": 10, + "admissionReviewVersions": .admissionReviewVersions, + "namespaceSelector": { + "matchExpressions": [ + { + "key": "namespace", + "operator": "In", + "values": [env(namespace)] + } + ] + } + } | del( + .name, + .deploymentName, + .generateName, + .webhookPath, + .containerPort, + .rules, + .failurePolicy, + .sideEffects, + .admissionReviewVersions, + .targetPort + ) + ' "${csv}" > "${webhook_file}" + done +} + extract_lvms_clusterrole_from_csv_by_service_account_name() { local service_account_name="$1" local csv="$2"