From 538005b98ba951598f83a878c9c96b2aa89385d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Ho=C3=9F?= Date: Sat, 4 Nov 2023 16:28:04 +0100 Subject: [PATCH] add ipfs-cluster/ipfs-operator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sebastian Hoß --- .reuse/dep5 | 4 + code-generator/src/catalog.rs | 8 + .../v1alpha1/circuitrelays.yaml | 72 +++++++ .../v1alpha1/ipfsclusters.yaml | 179 ++++++++++++++++++ kube-custom-resources-rs/Cargo.toml | 1 + .../cluster_ipfs_io_v1alpha1/circuitrelays.rs | 42 ++++ .../cluster_ipfs_io_v1alpha1/ipfsclusters.rs | 127 +++++++++++++ .../src/cluster_ipfs_io_v1alpha1/mod.rs | 2 + kube-custom-resources-rs/src/lib.rs | 2 + 9 files changed, 437 insertions(+) create mode 100644 crd-catalog/ipfs-cluster/ipfs-operator/cluster.ipfs.io/v1alpha1/circuitrelays.yaml create mode 100644 crd-catalog/ipfs-cluster/ipfs-operator/cluster.ipfs.io/v1alpha1/ipfsclusters.yaml create mode 100644 kube-custom-resources-rs/src/cluster_ipfs_io_v1alpha1/circuitrelays.rs create mode 100644 kube-custom-resources-rs/src/cluster_ipfs_io_v1alpha1/ipfsclusters.rs create mode 100644 kube-custom-resources-rs/src/cluster_ipfs_io_v1alpha1/mod.rs diff --git a/.reuse/dep5 b/.reuse/dep5 index a4dd6f24c..af42f5eb2 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -339,6 +339,10 @@ Files: crd-catalog/infinispan/infinispan-operator/* Copyright: The infinispan/infinispan-operator Authors License: Apache-2.0 +Files: crd-catalog/ipfs-cluster/ipfs-operator/* +Copyright: The ipfs-cluster/ipfs-operator Authors +License: Apache-2.0 + Files: crd-catalog/istio/istio/* Copyright: The istio/istio Authors License: Apache-2.0 diff --git a/code-generator/src/catalog.rs b/code-generator/src/catalog.rs index a881e9028..4b941c94e 100644 --- a/code-generator/src/catalog.rs +++ b/code-generator/src/catalog.rs @@ -865,6 +865,14 @@ pub const CRD_V1_SOURCES: &'static [UpstreamSource] = &[ "https://github.com/infinispan/infinispan-operator/blob/main/config/crd/bases/infinispan.org_restores.yaml", ], }, + UpstreamSource { + project_name: "ipfs-cluster/ipfs-operator", + license: APACHE_V2, + urls: &[ + "https://github.com/ipfs-cluster/ipfs-operator/blob/main/config/crd/bases/cluster.ipfs.io_circuitrelays.yaml", + "https://github.com/ipfs-cluster/ipfs-operator/blob/main/config/crd/bases/cluster.ipfs.io_ipfsclusters.yaml", + ], + }, UpstreamSource { project_name: "istio/istio", license: APACHE_V2, diff --git a/crd-catalog/ipfs-cluster/ipfs-operator/cluster.ipfs.io/v1alpha1/circuitrelays.yaml b/crd-catalog/ipfs-cluster/ipfs-operator/cluster.ipfs.io/v1alpha1/circuitrelays.yaml new file mode 100644 index 000000000..9c97d720e --- /dev/null +++ b/crd-catalog/ipfs-cluster/ipfs-operator/cluster.ipfs.io/v1alpha1/circuitrelays.yaml @@ -0,0 +1,72 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.8.0 + name: circuitrelays.cluster.ipfs.io +spec: + group: cluster.ipfs.io + names: + kind: CircuitRelay + listKind: CircuitRelayList + plural: circuitrelays + singular: circuitrelay + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: CircuitRelay is the Schema for the circuitrelays 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: CircuitRelaySpec Defines a specification for the RelayCircuit launched by Kubernetes. + properties: + swarmKeyRef: + description: SwarmKeyRef points to a multicodec-encoded v1 PSK stored within a secret somewhere. + properties: + keyName: + type: string + secretName: + type: string + required: + - keyName + - secretName + type: object + type: object + status: + properties: + addrInfo: + description: This is intended to mimic peer.AddrInfo. + properties: + addrs: + items: + type: string + type: array + id: + type: string + required: + - addrs + - id + type: object + required: + - addrInfo + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: '' + plural: '' + conditions: [] + storedVersions: [] diff --git a/crd-catalog/ipfs-cluster/ipfs-operator/cluster.ipfs.io/v1alpha1/ipfsclusters.yaml b/crd-catalog/ipfs-cluster/ipfs-operator/cluster.ipfs.io/v1alpha1/ipfsclusters.yaml new file mode 100644 index 000000000..b8aa64725 --- /dev/null +++ b/crd-catalog/ipfs-cluster/ipfs-operator/cluster.ipfs.io/v1alpha1/ipfsclusters.yaml @@ -0,0 +1,179 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.8.0 + name: ipfsclusters.cluster.ipfs.io +spec: + group: cluster.ipfs.io + names: + kind: IpfsCluster + listKind: IpfsClusterList + plural: ipfsclusters + singular: ipfscluster + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: IpfsCluster is the Schema for the ipfs 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: IpfsClusterSpec defines the desired state of the IpfsCluster. + properties: + clusterStorage: + anyOf: + - type: integer + - type: string + description: clusterStorage defines the amount of storage to be used by IPFS Cluster. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + follows: + description: follows defines the list of other IPFS Clusters this one should follow. + items: + properties: + name: + type: string + template: + type: string + required: + - name + - template + type: object + type: array + ipfsResources: + description: ipfsResources specifies the resource requirements for each IPFS container. If this value is omitted, then the operator will automatically determine these settings based on the storage sizes used. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + ipfsStorage: + anyOf: + - type: integer + - type: string + description: ipfsStorage defines the total storage to be allocated by this resource. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + networking: + description: networking defines network configuration settings. + properties: + circuitRelays: + description: circuitRelays defines how many CircuitRelays should be created. + format: int32 + type: integer + public: + default: true + description: public is a switch which defines whether this IPFSCluster will use the global IPFS network or create its own. + type: boolean + required: + - circuitRelays + type: object + replicas: + description: replicas sets the number of replicas of IPFS Cluster nodes we should be running. + format: int32 + type: integer + reprovider: + description: reprovider Describes the settings that each IPFS node should use when reproviding content. + properties: + interval: + description: Interval sets the time between rounds of reproviding local content to the routing system. Defaults to '12h'. + type: string + strategy: + description: Strategy specifies the reprovider strategy, defaults to 'all'. + enum: + - all + - pinned + - roots + type: string + type: object + required: + - clusterStorage + - ipfsStorage + - networking + - replicas + type: object + status: + properties: + circuitRelays: + items: + type: string + type: array + conditions: + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0.0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - 'True' + - 'False' + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: '' + plural: '' + conditions: [] + storedVersions: [] diff --git a/kube-custom-resources-rs/Cargo.toml b/kube-custom-resources-rs/Cargo.toml index 2a01538b7..76a9020e9 100644 --- a/kube-custom-resources-rs/Cargo.toml +++ b/kube-custom-resources-rs/Cargo.toml @@ -84,6 +84,7 @@ cilium_io_v2 = [] cilium_io_v2alpha1 = [] cloudformation_linki_space_v1alpha1 = [] cluster_clusterpedia_io_v1alpha2 = [] +cluster_ipfs_io_v1alpha1 = [] cluster_x_k8s_io_v1alpha4 = [] cluster_x_k8s_io_v1beta1 = [] clusters_clusternet_io_v1beta1 = [] diff --git a/kube-custom-resources-rs/src/cluster_ipfs_io_v1alpha1/circuitrelays.rs b/kube-custom-resources-rs/src/cluster_ipfs_io_v1alpha1/circuitrelays.rs new file mode 100644 index 000000000..0dca31245 --- /dev/null +++ b/kube-custom-resources-rs/src/cluster_ipfs_io_v1alpha1/circuitrelays.rs @@ -0,0 +1,42 @@ +// WARNING: generated by kopium - manual changes will be overwritten +// kopium command: kopium --docs --filename ./crd-catalog/ipfs-cluster/ipfs-operator/cluster.ipfs.io/v1alpha1/circuitrelays.yaml +// kopium version: 0.16.1 + +use kube::CustomResource; +use serde::{Serialize, Deserialize}; + +/// CircuitRelaySpec Defines a specification for the RelayCircuit launched by Kubernetes. +#[derive(CustomResource, Serialize, Deserialize, Clone, Debug)] +#[kube(group = "cluster.ipfs.io", version = "v1alpha1", kind = "CircuitRelay", plural = "circuitrelays")] +#[kube(namespaced)] +#[kube(status = "CircuitRelayStatus")] +#[kube(schema = "disabled")] +pub struct CircuitRelaySpec { + /// SwarmKeyRef points to a multicodec-encoded v1 PSK stored within a secret somewhere. + #[serde(default, skip_serializing_if = "Option::is_none", rename = "swarmKeyRef")] + pub swarm_key_ref: Option, +} + +/// SwarmKeyRef points to a multicodec-encoded v1 PSK stored within a secret somewhere. +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct CircuitRelaySwarmKeyRef { + #[serde(rename = "keyName")] + pub key_name: String, + #[serde(rename = "secretName")] + pub secret_name: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct CircuitRelayStatus { + /// This is intended to mimic peer.AddrInfo. + #[serde(rename = "addrInfo")] + pub addr_info: CircuitRelayStatusAddrInfo, +} + +/// This is intended to mimic peer.AddrInfo. +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct CircuitRelayStatusAddrInfo { + pub addrs: Vec, + pub id: String, +} + diff --git a/kube-custom-resources-rs/src/cluster_ipfs_io_v1alpha1/ipfsclusters.rs b/kube-custom-resources-rs/src/cluster_ipfs_io_v1alpha1/ipfsclusters.rs new file mode 100644 index 000000000..654ada2db --- /dev/null +++ b/kube-custom-resources-rs/src/cluster_ipfs_io_v1alpha1/ipfsclusters.rs @@ -0,0 +1,127 @@ +// WARNING: generated by kopium - manual changes will be overwritten +// kopium command: kopium --docs --filename ./crd-catalog/ipfs-cluster/ipfs-operator/cluster.ipfs.io/v1alpha1/ipfsclusters.yaml +// kopium version: 0.16.1 + +use kube::CustomResource; +use serde::{Serialize, Deserialize}; +use std::collections::BTreeMap; +use k8s_openapi::apimachinery::pkg::util::intstr::IntOrString; + +/// IpfsClusterSpec defines the desired state of the IpfsCluster. +#[derive(CustomResource, Serialize, Deserialize, Clone, Debug)] +#[kube(group = "cluster.ipfs.io", version = "v1alpha1", kind = "IpfsCluster", plural = "ipfsclusters")] +#[kube(namespaced)] +#[kube(status = "IpfsClusterStatus")] +#[kube(schema = "disabled")] +pub struct IpfsClusterSpec { + /// clusterStorage defines the amount of storage to be used by IPFS Cluster. + #[serde(rename = "clusterStorage")] + pub cluster_storage: IntOrString, + /// follows defines the list of other IPFS Clusters this one should follow. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub follows: Option>, + /// ipfsResources specifies the resource requirements for each IPFS container. If this value is omitted, then the operator will automatically determine these settings based on the storage sizes used. + #[serde(default, skip_serializing_if = "Option::is_none", rename = "ipfsResources")] + pub ipfs_resources: Option, + /// ipfsStorage defines the total storage to be allocated by this resource. + #[serde(rename = "ipfsStorage")] + pub ipfs_storage: IntOrString, + /// networking defines network configuration settings. + pub networking: IpfsClusterNetworking, + /// replicas sets the number of replicas of IPFS Cluster nodes we should be running. + pub replicas: i32, + /// reprovider Describes the settings that each IPFS node should use when reproviding content. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub reprovider: Option, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct IpfsClusterFollows { + pub name: String, + pub template: String, +} + +/// ipfsResources specifies the resource requirements for each IPFS container. If this value is omitted, then the operator will automatically determine these settings based on the storage sizes used. +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct IpfsClusterIpfsResources { + /// Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + #[serde(default, skip_serializing_if = "Option::is_none")] + pub limits: Option>, + /// Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + #[serde(default, skip_serializing_if = "Option::is_none")] + pub requests: Option>, +} + +/// networking defines network configuration settings. +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct IpfsClusterNetworking { + /// circuitRelays defines how many CircuitRelays should be created. + #[serde(rename = "circuitRelays")] + pub circuit_relays: i32, + /// public is a switch which defines whether this IPFSCluster will use the global IPFS network or create its own. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub public: Option, +} + +/// reprovider Describes the settings that each IPFS node should use when reproviding content. +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct IpfsClusterReprovider { + /// Interval sets the time between rounds of reproviding local content to the routing system. Defaults to '12h'. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub interval: Option, + /// Strategy specifies the reprovider strategy, defaults to 'all'. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub strategy: Option, +} + +/// reprovider Describes the settings that each IPFS node should use when reproviding content. +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum IpfsClusterReproviderStrategy { + #[serde(rename = "all")] + All, + #[serde(rename = "pinned")] + Pinned, + #[serde(rename = "roots")] + Roots, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct IpfsClusterStatus { + #[serde(default, skip_serializing_if = "Option::is_none", rename = "circuitRelays")] + pub circuit_relays: Option>, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub conditions: Option>, +} + +/// Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, +/// type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: "Available", "Progressing", and "Degraded" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` +/// // other fields } +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct IpfsClusterStatusConditions { + /// lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + #[serde(rename = "lastTransitionTime")] + pub last_transition_time: String, + /// message is a human readable message indicating details about the transition. This may be an empty string. + pub message: String, + /// observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + #[serde(default, skip_serializing_if = "Option::is_none", rename = "observedGeneration")] + pub observed_generation: Option, + /// reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + pub reason: String, + /// status of the condition, one of True, False, Unknown. + pub status: IpfsClusterStatusConditionsStatus, + /// type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + #[serde(rename = "type")] + pub r#type: String, +} + +/// Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, +/// type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: "Available", "Progressing", and "Degraded" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` +/// // other fields } +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum IpfsClusterStatusConditionsStatus { + True, + False, + Unknown, +} + diff --git a/kube-custom-resources-rs/src/cluster_ipfs_io_v1alpha1/mod.rs b/kube-custom-resources-rs/src/cluster_ipfs_io_v1alpha1/mod.rs new file mode 100644 index 000000000..1bfc7a293 --- /dev/null +++ b/kube-custom-resources-rs/src/cluster_ipfs_io_v1alpha1/mod.rs @@ -0,0 +1,2 @@ +pub mod circuitrelays; +pub mod ipfsclusters; diff --git a/kube-custom-resources-rs/src/lib.rs b/kube-custom-resources-rs/src/lib.rs index c72dd7fd7..1d59fcff5 100644 --- a/kube-custom-resources-rs/src/lib.rs +++ b/kube-custom-resources-rs/src/lib.rs @@ -114,6 +114,8 @@ pub mod cilium_io_v2alpha1; pub mod cloudformation_linki_space_v1alpha1; #[cfg(feature = "cluster_clusterpedia_io_v1alpha2")] pub mod cluster_clusterpedia_io_v1alpha2; +#[cfg(feature = "cluster_ipfs_io_v1alpha1")] +pub mod cluster_ipfs_io_v1alpha1; #[cfg(feature = "cluster_x_k8s_io_v1alpha4")] pub mod cluster_x_k8s_io_v1alpha4; #[cfg(feature = "cluster_x_k8s_io_v1beta1")]