diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 9b1f5738fea..410add77696 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -4369,6 +4369,20 @@ ], "type": "object" }, + "io.k8s.api.core.v1.ClaimSource": { + "description": "ClaimSource describes a reference to a ResourceClaim.\n\nExactly one of these fields should be set. Consumers of this type must treat an empty object as if it has an unknown value.", + "properties": { + "resourceClaimName": { + "description": "ResourceClaimName is the name of a ResourceClaim object in the same namespace as this pod.", + "type": "string" + }, + "resourceClaimTemplateName": { + "description": "ResourceClaimTemplateName is the name of a ResourceClaimTemplate object in the same namespace as this pod.\n\nThe template will be used to create a new ResourceClaim, which will be bound to this pod. When this pod is deleted, the ResourceClaim will also be deleted. The name of the ResourceClaim will be -, where is the PodResourceClaim.Name. Pod validation will reject the pod if the concatenated name is not valid for a ResourceClaim (e.g. too long).\n\nAn existing ResourceClaim with that name that is not owned by the pod will not be used for the pod to avoid using an unrelated resource by mistake. Scheduling and pod startup are then blocked until the unrelated ResourceClaim is removed.\n\nThis field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim.", + "type": "string" + } + }, + "type": "object" + }, "io.k8s.api.core.v1.ClientIPConfig": { "description": "ClientIPConfig represents the configurations of Client IP based session affinity.", "properties": { @@ -7573,6 +7587,23 @@ ], "type": "object" }, + "io.k8s.api.core.v1.PodResourceClaim": { + "description": "PodResourceClaim references exactly one ResourceClaim through a ClaimSource. It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name.", + "properties": { + "name": { + "description": "Name uniquely identifies this resource claim inside the pod. This must be a DNS_LABEL.", + "type": "string" + }, + "source": { + "$ref": "#/definitions/io.k8s.api.core.v1.ClaimSource", + "description": "Source describes where to find the ResourceClaim." + } + }, + "required": [ + "name" + ], + "type": "object" + }, "io.k8s.api.core.v1.PodSchedulingGate": { "description": "PodSchedulingGate is associated to a Pod to guard its scheduling.", "properties": { @@ -7778,6 +7809,19 @@ }, "type": "array" }, + "resourceClaims": { + "description": "ResourceClaims defines which ResourceClaims must be allocated and reserved before the Pod is allowed to start. The resources will be made available to those containers which consume them by name.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.PodResourceClaim" + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "name" + ], + "x-kubernetes-list-type": "map", + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge,retainKeys" + }, "restartPolicy": { "description": "Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy\n\n", "type": "string" @@ -8448,6 +8492,19 @@ ], "type": "object" }, + "io.k8s.api.core.v1.ResourceClaim": { + "description": "ResourceClaim references one entry in PodSpec.ResourceClaims.", + "properties": { + "name": { + "description": "Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, "io.k8s.api.core.v1.ResourceFieldSelector": { "description": "ResourceFieldSelector represents container resources (cpu, memory) and their output format", "properties": { @@ -8585,6 +8642,14 @@ "io.k8s.api.core.v1.ResourceRequirements": { "description": "ResourceRequirements describes the compute resource requirements.", "properties": { + "claims": { + "description": "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", + "items": { + "$ref": "#/definitions/io.k8s.api.core.v1.ResourceClaim" + }, + "type": "array", + "x-kubernetes-list-type": "set" + }, "limits": { "additionalProperties": { "$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity" @@ -12764,6 +12829,500 @@ "type": "object", "x-kubernetes-map-type": "atomic" }, + "io.k8s.api.resource.v1alpha1.AllocationResult": { + "description": "AllocationResult contains attributed of an allocated resource.", + "properties": { + "availableOnNodes": { + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSelector", + "description": "This field will get set by the resource driver after it has allocated the resource driver to inform the scheduler where it can schedule Pods using the ResourceClaim.\n\nSetting this field is optional. If null, the resource is available everywhere." + }, + "resourceHandle": { + "description": "ResourceHandle contains arbitrary data returned by the driver after a successful allocation. This is opaque for Kubernetes. Driver documentation may explain to users how to interpret this data if needed.\n\nThe maximum size of this field is 16KiB. This may get increased in the future, but not reduced.", + "type": "string" + }, + "shareable": { + "description": "Shareable determines whether the resource supports more than one consumer at a time.", + "type": "boolean" + } + }, + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.PodScheduling": { + "description": "PodScheduling objects hold information that is needed to schedule a Pod with ResourceClaims that use \"WaitForFirstConsumer\" allocation mode.\n\nThis is an alpha type and requires enabling the DynamicResourceAllocation feature gate.", + "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": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta", + "description": "Standard object metadata" + }, + "spec": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodSchedulingSpec", + "description": "Spec describes where resources for the Pod are needed." + }, + "status": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodSchedulingStatus", + "description": "Status describes where resources for the Pod can be allocated." + } + }, + "required": [ + "spec" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.PodSchedulingList": { + "description": "PodSchedulingList is a collection of Pod scheduling objects.", + "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" + }, + "items": { + "description": "Items is the list of PodScheduling objects.", + "items": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + }, + "type": "array" + }, + "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": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta", + "description": "Standard list metadata" + } + }, + "required": [ + "items" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "PodSchedulingList", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.PodSchedulingSpec": { + "description": "PodSchedulingSpec describes where resources for the Pod are needed.", + "properties": { + "potentialNodes": { + "description": "PotentialNodes lists nodes where the Pod might be able to run.\n\nThe size of this field is limited to 128. This is large enough for many clusters. Larger clusters may need more attempts to find a node that suits all pending resources. This may get increased in the future, but not reduced.", + "items": { + "type": "string" + }, + "type": "array", + "x-kubernetes-list-type": "set" + }, + "selectedNode": { + "description": "SelectedNode is the node for which allocation of ResourceClaims that are referenced by the Pod and that use \"WaitForFirstConsumer\" allocation is to be attempted.", + "type": "string" + } + }, + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.PodSchedulingStatus": { + "description": "PodSchedulingStatus describes where resources for the Pod can be allocated.", + "properties": { + "resourceClaims": { + "description": "ResourceClaims describes resource availability for each pod.spec.resourceClaim entry where the corresponding ResourceClaim uses \"WaitForFirstConsumer\" allocation mode.", + "items": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimSchedulingStatus" + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "name" + ], + "x-kubernetes-list-type": "map" + } + }, + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClaim": { + "description": "ResourceClaim describes which resources are needed by a resource consumer. Its status tracks whether the resource has been allocated and what the resulting attributes are.\n\nThis is an alpha type and requires enabling the DynamicResourceAllocation feature gate.", + "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": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta", + "description": "Standard object metadata" + }, + "spec": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimSpec", + "description": "Spec describes the desired attributes of a resource that then needs to be allocated. It can only be set once when creating the ResourceClaim." + }, + "status": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimStatus", + "description": "Status describes whether the resource is available and with which attributes." + } + }, + "required": [ + "spec" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimConsumerReference": { + "description": "ResourceClaimConsumerReference contains enough information to let you locate the consumer of a ResourceClaim. The user must be a resource in the same namespace as the ResourceClaim.", + "properties": { + "apiGroup": { + "description": "APIGroup is the group for the resource being referenced. It is empty for the core API. This matches the group in the APIVersion that is used when creating the resources.", + "type": "string" + }, + "name": { + "description": "Name is the name of resource being referenced.", + "type": "string" + }, + "resource": { + "description": "Resource is the type of resource being referenced, for example \"pods\".", + "type": "string" + }, + "uid": { + "description": "UID identifies exactly one incarnation of the resource.", + "type": "string" + } + }, + "required": [ + "resource", + "name", + "uid" + ], + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimList": { + "description": "ResourceClaimList is a collection of claims.", + "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" + }, + "items": { + "description": "Items is the list of resource claims.", + "items": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + }, + "type": "array" + }, + "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": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta", + "description": "Standard list metadata" + } + }, + "required": [ + "items" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "ResourceClaimList", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimParametersReference": { + "description": "ResourceClaimParametersReference contains enough information to let you locate the parameters for a ResourceClaim. The object must be in the same namespace as the ResourceClaim.", + "properties": { + "apiGroup": { + "description": "APIGroup is the group for the resource being referenced. It is empty for the core API. This matches the group in the APIVersion that is used when creating the resources.", + "type": "string" + }, + "kind": { + "description": "Kind is the type of resource being referenced. This is the same value as in the parameter object's metadata, for example \"ConfigMap\".", + "type": "string" + }, + "name": { + "description": "Name is the name of resource being referenced.", + "type": "string" + } + }, + "required": [ + "kind", + "name" + ], + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimSchedulingStatus": { + "description": "ResourceClaimSchedulingStatus contains information about one particular ResourceClaim with \"WaitForFirstConsumer\" allocation mode.", + "properties": { + "name": { + "description": "Name matches the pod.spec.resourceClaims[*].Name field.", + "type": "string" + }, + "unsuitableNodes": { + "description": "UnsuitableNodes lists nodes that the ResourceClaim cannot be allocated for.\n\nThe size of this field is limited to 128, the same as for PodSchedulingSpec.PotentialNodes. This may get increased in the future, but not reduced.", + "items": { + "type": "string" + }, + "type": "array", + "x-kubernetes-list-type": "set" + } + }, + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimSpec": { + "description": "ResourceClaimSpec defines how a resource is to be allocated.", + "properties": { + "allocationMode": { + "description": "Allocation can start immediately or when a Pod wants to use the resource. \"WaitForFirstConsumer\" is the default.", + "type": "string" + }, + "parametersRef": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimParametersReference", + "description": "ParametersRef references a separate object with arbitrary parameters that will be used by the driver when allocating a resource for the claim.\n\nThe object must be in the same namespace as the ResourceClaim." + }, + "resourceClassName": { + "description": "ResourceClassName references the driver and additional parameters via the name of a ResourceClass that was created as part of the driver deployment.", + "type": "string" + } + }, + "required": [ + "resourceClassName" + ], + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimStatus": { + "description": "ResourceClaimStatus tracks whether the resource has been allocated and what the resulting attributes are.", + "properties": { + "allocation": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.AllocationResult", + "description": "Allocation is set by the resource driver once a resource has been allocated successfully. If this is not specified, the resource is not yet allocated." + }, + "deallocationRequested": { + "description": "DeallocationRequested indicates that a ResourceClaim is to be deallocated.\n\nThe driver then must deallocate this claim and reset the field together with clearing the Allocation field.\n\nWhile DeallocationRequested is set, no new consumers may be added to ReservedFor.", + "type": "boolean" + }, + "driverName": { + "description": "DriverName is a copy of the driver name from the ResourceClass at the time when allocation started.", + "type": "string" + }, + "reservedFor": { + "description": "ReservedFor indicates which entities are currently allowed to use the claim. A Pod which references a ResourceClaim which is not reserved for that Pod will not be started.\n\nThere can be at most 32 such reservations. This may get increased in the future, but not reduced.", + "items": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimConsumerReference" + }, + "type": "array", + "x-kubernetes-list-type": "set" + } + }, + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimTemplate": { + "description": "ResourceClaimTemplate is used to produce ResourceClaim objects.", + "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": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta", + "description": "Standard object metadata" + }, + "spec": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateSpec", + "description": "Describes the ResourceClaim that is to be generated.\n\nThis field is immutable. A ResourceClaim will get created by the control plane for a Pod when needed and then not get updated anymore." + } + }, + "required": [ + "spec" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList": { + "description": "ResourceClaimTemplateList is a collection of claim templates.", + "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" + }, + "items": { + "description": "Items is the list of resource claim templates.", + "items": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + }, + "type": "array" + }, + "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": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta", + "description": "Standard list metadata" + } + }, + "required": [ + "items" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplateList", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimTemplateSpec": { + "description": "ResourceClaimTemplateSpec contains the metadata and fields for a ResourceClaim.", + "properties": { + "metadata": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta", + "description": "ObjectMeta may contain labels and annotations that will be copied into the PVC when creating it. No other fields are allowed and will be rejected during validation." + }, + "spec": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimSpec", + "description": "Spec for the ResourceClaim. The entire content is copied unchanged into the ResourceClaim that gets created from this template. The same fields as in a ResourceClaim are also valid here." + } + }, + "required": [ + "spec" + ], + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClass": { + "description": "ResourceClass is used by administrators to influence how resources are allocated.\n\nThis is an alpha type and requires enabling the DynamicResourceAllocation feature gate.", + "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" + }, + "driverName": { + "description": "DriverName defines the name of the dynamic resource driver that is used for allocation of a ResourceClaim that uses this class.\n\nResource drivers have a unique name in forward domain order (acme.example.com).", + "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": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta", + "description": "Standard object metadata" + }, + "parametersRef": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClassParametersReference", + "description": "ParametersRef references an arbitrary separate object that may hold parameters that will be used by the driver when allocating a resource that uses this class. A dynamic resource driver can distinguish between parameters stored here and and those stored in ResourceClaimSpec." + }, + "suitableNodes": { + "$ref": "#/definitions/io.k8s.api.core.v1.NodeSelector", + "description": "Only nodes matching the selector will be considered by the scheduler when trying to find a Node that fits a Pod when that Pod uses a ResourceClaim that has not been allocated yet.\n\nSetting this field is optional. If null, all nodes are candidates." + } + }, + "required": [ + "driverName" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.ResourceClassList": { + "description": "ResourceClassList is a collection of classes.", + "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" + }, + "items": { + "description": "Items is the list of resource classes.", + "items": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + }, + "type": "array" + }, + "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": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta", + "description": "Standard list metadata" + } + }, + "required": [ + "items" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "ResourceClassList", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.ResourceClassParametersReference": { + "description": "ResourceClassParametersReference contains enough information to let you locate the parameters for a ResourceClass.", + "properties": { + "apiGroup": { + "description": "APIGroup is the group for the resource being referenced. It is empty for the core API. This matches the group in the APIVersion that is used when creating the resources.", + "type": "string" + }, + "kind": { + "description": "Kind is the type of resource being referenced. This is the same value as in the parameter object's metadata.", + "type": "string" + }, + "name": { + "description": "Name is the name of resource being referenced.", + "type": "string" + }, + "namespace": { + "description": "Namespace that contains the referenced resource. Must be empty for cluster-scoped resources and non-empty for namespaced resources.", + "type": "string" + } + }, + "required": [ + "kind", + "name" + ], + "type": "object" + }, "io.k8s.api.scheduling.v1.PriorityClass": { "description": "PriorityClass defines mapping from a priority class name to the priority integer value. The value can be any valid integer.", "properties": { @@ -14721,6 +15280,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -15087,6 +15651,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -15414,6 +15983,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", @@ -75237,6 +75811,4578 @@ } ] }, + "/apis/resource.k8s.io/": { + "get": { + "consumes": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "description": "get information of a group", + "operationId": "getResourceAPIGroup", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource" + ] + } + }, + "/apis/resource.k8s.io/v1alpha1/": { + "get": { + "consumes": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "description": "get available resources", + "operationId": "getResourceV1alpha1APIResources", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ] + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/podschedulings": { + "delete": { + "consumes": [ + "*/*" + ], + "description": "delete collection of PodScheduling", + "operationId": "deleteResourceV1alpha1CollectionNamespacedPodScheduling", + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "deletecollection", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "get": { + "consumes": [ + "*/*" + ], + "description": "list or watch objects of kind PodScheduling", + "operationId": "listResourceV1alpha1NamespacedPodScheduling", + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodSchedulingList" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + } + ], + "post": { + "consumes": [ + "*/*" + ], + "description": "create a PodScheduling", + "operationId": "createResourceV1alpha1NamespacedPodScheduling", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "post", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/podschedulings/{name}": { + "delete": { + "consumes": [ + "*/*" + ], + "description": "delete a PodScheduling", + "operationId": "deleteResourceV1alpha1NamespacedPodScheduling", + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "delete", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "get": { + "consumes": [ + "*/*" + ], + "description": "read the specified PodScheduling", + "operationId": "readResourceV1alpha1NamespacedPodScheduling", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "name of the PodScheduling", + "in": "path", + "name": "name", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + } + ], + "patch": { + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json", + "application/apply-patch+yaml" + ], + "description": "partially update the specified PodScheduling", + "operationId": "patchResourceV1alpha1NamespacedPodScheduling", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + }, + { + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "in": "query", + "name": "force", + "type": "boolean", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "put": { + "consumes": [ + "*/*" + ], + "description": "replace the specified PodScheduling", + "operationId": "replaceResourceV1alpha1NamespacedPodScheduling", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/podschedulings/{name}/status": { + "get": { + "consumes": [ + "*/*" + ], + "description": "read status of the specified PodScheduling", + "operationId": "readResourceV1alpha1NamespacedPodSchedulingStatus", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "name of the PodScheduling", + "in": "path", + "name": "name", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + } + ], + "patch": { + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json", + "application/apply-patch+yaml" + ], + "description": "partially update status of the specified PodScheduling", + "operationId": "patchResourceV1alpha1NamespacedPodSchedulingStatus", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + }, + { + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "in": "query", + "name": "force", + "type": "boolean", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "put": { + "consumes": [ + "*/*" + ], + "description": "replace status of the specified PodScheduling", + "operationId": "replaceResourceV1alpha1NamespacedPodSchedulingStatus", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/resourceclaims": { + "delete": { + "consumes": [ + "*/*" + ], + "description": "delete collection of ResourceClaim", + "operationId": "deleteResourceV1alpha1CollectionNamespacedResourceClaim", + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "deletecollection", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "get": { + "consumes": [ + "*/*" + ], + "description": "list or watch objects of kind ResourceClaim", + "operationId": "listResourceV1alpha1NamespacedResourceClaim", + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimList" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + } + ], + "post": { + "consumes": [ + "*/*" + ], + "description": "create a ResourceClaim", + "operationId": "createResourceV1alpha1NamespacedResourceClaim", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "post", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/resourceclaims/{name}": { + "delete": { + "consumes": [ + "*/*" + ], + "description": "delete a ResourceClaim", + "operationId": "deleteResourceV1alpha1NamespacedResourceClaim", + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "delete", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "get": { + "consumes": [ + "*/*" + ], + "description": "read the specified ResourceClaim", + "operationId": "readResourceV1alpha1NamespacedResourceClaim", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "name of the ResourceClaim", + "in": "path", + "name": "name", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + } + ], + "patch": { + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json", + "application/apply-patch+yaml" + ], + "description": "partially update the specified ResourceClaim", + "operationId": "patchResourceV1alpha1NamespacedResourceClaim", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + }, + { + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "in": "query", + "name": "force", + "type": "boolean", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "put": { + "consumes": [ + "*/*" + ], + "description": "replace the specified ResourceClaim", + "operationId": "replaceResourceV1alpha1NamespacedResourceClaim", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/resourceclaims/{name}/status": { + "get": { + "consumes": [ + "*/*" + ], + "description": "read status of the specified ResourceClaim", + "operationId": "readResourceV1alpha1NamespacedResourceClaimStatus", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "name of the ResourceClaim", + "in": "path", + "name": "name", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + } + ], + "patch": { + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json", + "application/apply-patch+yaml" + ], + "description": "partially update status of the specified ResourceClaim", + "operationId": "patchResourceV1alpha1NamespacedResourceClaimStatus", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + }, + { + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "in": "query", + "name": "force", + "type": "boolean", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "put": { + "consumes": [ + "*/*" + ], + "description": "replace status of the specified ResourceClaim", + "operationId": "replaceResourceV1alpha1NamespacedResourceClaimStatus", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/resourceclaimtemplates": { + "delete": { + "consumes": [ + "*/*" + ], + "description": "delete collection of ResourceClaimTemplate", + "operationId": "deleteResourceV1alpha1CollectionNamespacedResourceClaimTemplate", + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "deletecollection", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "get": { + "consumes": [ + "*/*" + ], + "description": "list or watch objects of kind ResourceClaimTemplate", + "operationId": "listResourceV1alpha1NamespacedResourceClaimTemplate", + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + } + ], + "post": { + "consumes": [ + "*/*" + ], + "description": "create a ResourceClaimTemplate", + "operationId": "createResourceV1alpha1NamespacedResourceClaimTemplate", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "post", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/resourceclaimtemplates/{name}": { + "delete": { + "consumes": [ + "*/*" + ], + "description": "delete a ResourceClaimTemplate", + "operationId": "deleteResourceV1alpha1NamespacedResourceClaimTemplate", + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "delete", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "get": { + "consumes": [ + "*/*" + ], + "description": "read the specified ResourceClaimTemplate", + "operationId": "readResourceV1alpha1NamespacedResourceClaimTemplate", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "name of the ResourceClaimTemplate", + "in": "path", + "name": "name", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + } + ], + "patch": { + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json", + "application/apply-patch+yaml" + ], + "description": "partially update the specified ResourceClaimTemplate", + "operationId": "patchResourceV1alpha1NamespacedResourceClaimTemplate", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + }, + { + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "in": "query", + "name": "force", + "type": "boolean", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "put": { + "consumes": [ + "*/*" + ], + "description": "replace the specified ResourceClaimTemplate", + "operationId": "replaceResourceV1alpha1NamespacedResourceClaimTemplate", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/podschedulings": { + "get": { + "consumes": [ + "*/*" + ], + "description": "list or watch objects of kind PodScheduling", + "operationId": "listResourceV1alpha1PodSchedulingForAllNamespaces", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.PodSchedulingList" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/resourceclaims": { + "get": { + "consumes": [ + "*/*" + ], + "description": "list or watch objects of kind ResourceClaim", + "operationId": "listResourceV1alpha1ResourceClaimForAllNamespaces", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimList" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/resourceclaimtemplates": { + "get": { + "consumes": [ + "*/*" + ], + "description": "list or watch objects of kind ResourceClaimTemplate", + "operationId": "listResourceV1alpha1ResourceClaimTemplateForAllNamespaces", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/resourceclasses": { + "delete": { + "consumes": [ + "*/*" + ], + "description": "delete collection of ResourceClass", + "operationId": "deleteResourceV1alpha1CollectionResourceClass", + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "deletecollection", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "get": { + "consumes": [ + "*/*" + ], + "description": "list or watch objects of kind ResourceClass", + "operationId": "listResourceV1alpha1ResourceClass", + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClassList" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + } + ], + "post": { + "consumes": [ + "*/*" + ], + "description": "create a ResourceClass", + "operationId": "createResourceV1alpha1ResourceClass", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "post", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/resourceclasses/{name}": { + "delete": { + "consumes": [ + "*/*" + ], + "description": "delete a ResourceClass", + "operationId": "deleteResourceV1alpha1ResourceClass", + "parameters": [ + { + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "delete", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "get": { + "consumes": [ + "*/*" + ], + "description": "read the specified ResourceClass", + "operationId": "readResourceV1alpha1ResourceClass", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "name of the ResourceClass", + "in": "path", + "name": "name", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + } + ], + "patch": { + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json", + "application/apply-patch+yaml" + ], + "description": "partially update the specified ResourceClass", + "operationId": "patchResourceV1alpha1ResourceClass", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + }, + { + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "in": "query", + "name": "force", + "type": "boolean", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "put": { + "consumes": [ + "*/*" + ], + "description": "replace the specified ResourceClass", + "operationId": "replaceResourceV1alpha1ResourceClass", + "parameters": [ + { + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "type": "string", + "uniqueItems": true + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "type": "string", + "uniqueItems": true + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/watch/namespaces/{namespace}/podschedulings": { + "get": { + "consumes": [ + "*/*" + ], + "description": "watch individual changes to a list of PodScheduling. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1NamespacedPodSchedulingList", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/namespaces/{namespace}/podschedulings/{name}": { + "get": { + "consumes": [ + "*/*" + ], + "description": "watch changes to an object of kind PodScheduling. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.", + "operationId": "watchResourceV1alpha1NamespacedPodScheduling", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "name of the PodScheduling", + "in": "path", + "name": "name", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/namespaces/{namespace}/resourceclaims": { + "get": { + "consumes": [ + "*/*" + ], + "description": "watch individual changes to a list of ResourceClaim. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1NamespacedResourceClaimList", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/namespaces/{namespace}/resourceclaims/{name}": { + "get": { + "consumes": [ + "*/*" + ], + "description": "watch changes to an object of kind ResourceClaim. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.", + "operationId": "watchResourceV1alpha1NamespacedResourceClaim", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "name of the ResourceClaim", + "in": "path", + "name": "name", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/namespaces/{namespace}/resourceclaimtemplates": { + "get": { + "consumes": [ + "*/*" + ], + "description": "watch individual changes to a list of ResourceClaimTemplate. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1NamespacedResourceClaimTemplateList", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/namespaces/{namespace}/resourceclaimtemplates/{name}": { + "get": { + "consumes": [ + "*/*" + ], + "description": "watch changes to an object of kind ResourceClaimTemplate. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.", + "operationId": "watchResourceV1alpha1NamespacedResourceClaimTemplate", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "name of the ResourceClaimTemplate", + "in": "path", + "name": "name", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/podschedulings": { + "get": { + "consumes": [ + "*/*" + ], + "description": "watch individual changes to a list of PodScheduling. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1PodSchedulingListForAllNamespaces", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/resourceclaims": { + "get": { + "consumes": [ + "*/*" + ], + "description": "watch individual changes to a list of ResourceClaim. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1ResourceClaimListForAllNamespaces", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/resourceclaimtemplates": { + "get": { + "consumes": [ + "*/*" + ], + "description": "watch individual changes to a list of ResourceClaimTemplate. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1ResourceClaimTemplateListForAllNamespaces", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/resourceclasses": { + "get": { + "consumes": [ + "*/*" + ], + "description": "watch individual changes to a list of ResourceClass. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1ResourceClassList", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/resourceclasses/{name}": { + "get": { + "consumes": [ + "*/*" + ], + "description": "watch changes to an object of kind ResourceClass. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.", + "operationId": "watchResourceV1alpha1ResourceClass", + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "schemes": [ + "https" + ], + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "type": "boolean", + "uniqueItems": true + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "type": "string", + "uniqueItems": true + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "type": "integer", + "uniqueItems": true + }, + { + "description": "name of the ResourceClass", + "in": "path", + "name": "name", + "required": true, + "type": "string", + "uniqueItems": true + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "type": "string", + "uniqueItems": true + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "type": "string", + "uniqueItems": true + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "type": "integer", + "uniqueItems": true + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "type": "boolean", + "uniqueItems": true + } + ] + }, "/apis/scheduling.k8s.io/": { "get": { "consumes": [ diff --git a/api/openapi-spec/v3/api__v1_openapi.json b/api/openapi-spec/v3/api__v1_openapi.json index 8c73deeb599..511bdec32c6 100644 --- a/api/openapi-spec/v3/api__v1_openapi.json +++ b/api/openapi-spec/v3/api__v1_openapi.json @@ -691,6 +691,20 @@ ], "type": "object" }, + "io.k8s.api.core.v1.ClaimSource": { + "description": "ClaimSource describes a reference to a ResourceClaim.\n\nExactly one of these fields should be set. Consumers of this type must treat an empty object as if it has an unknown value.", + "properties": { + "resourceClaimName": { + "description": "ResourceClaimName is the name of a ResourceClaim object in the same namespace as this pod.", + "type": "string" + }, + "resourceClaimTemplateName": { + "description": "ResourceClaimTemplateName is the name of a ResourceClaimTemplate object in the same namespace as this pod.\n\nThe template will be used to create a new ResourceClaim, which will be bound to this pod. When this pod is deleted, the ResourceClaim will also be deleted. The name of the ResourceClaim will be -, where is the PodResourceClaim.Name. Pod validation will reject the pod if the concatenated name is not valid for a ResourceClaim (e.g. too long).\n\nAn existing ResourceClaim with that name that is not owned by the pod will not be used for the pod to avoid using an unrelated resource by mistake. Scheduling and pod startup are then blocked until the unrelated ResourceClaim is removed.\n\nThis field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim.", + "type": "string" + } + }, + "type": "object" + }, "io.k8s.api.core.v1.ClientIPConfig": { "description": "ClientIPConfig represents the configurations of Client IP based session affinity.", "properties": { @@ -4869,6 +4883,29 @@ ], "type": "object" }, + "io.k8s.api.core.v1.PodResourceClaim": { + "description": "PodResourceClaim references exactly one ResourceClaim through a ClaimSource. It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name.", + "properties": { + "name": { + "default": "", + "description": "Name uniquely identifies this resource claim inside the pod. This must be a DNS_LABEL.", + "type": "string" + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.ClaimSource" + } + ], + "default": {}, + "description": "Source describes where to find the ResourceClaim." + } + }, + "required": [ + "name" + ], + "type": "object" + }, "io.k8s.api.core.v1.PodSchedulingGate": { "description": "PodSchedulingGate is associated to a Pod to guard its scheduling.", "properties": { @@ -5141,6 +5178,24 @@ }, "type": "array" }, + "resourceClaims": { + "description": "ResourceClaims defines which ResourceClaims must be allocated and reserved before the Pod is allowed to start. The resources will be made available to those containers which consume them by name.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.PodResourceClaim" + } + ], + "default": {} + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "name" + ], + "x-kubernetes-list-type": "map", + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge,retainKeys" + }, "restartPolicy": { "description": "Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy\n\n", "type": "string" @@ -5981,6 +6036,20 @@ ], "type": "object" }, + "io.k8s.api.core.v1.ResourceClaim": { + "description": "ResourceClaim references one entry in PodSpec.ResourceClaims.", + "properties": { + "name": { + "default": "", + "description": "Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, "io.k8s.api.core.v1.ResourceFieldSelector": { "description": "ResourceFieldSelector represents container resources (cpu, memory) and their output format", "properties": { @@ -6169,6 +6238,19 @@ "io.k8s.api.core.v1.ResourceRequirements": { "description": "ResourceRequirements describes the compute resource requirements.", "properties": { + "claims": { + "description": "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.ResourceClaim" + } + ], + "default": {} + }, + "type": "array", + "x-kubernetes-list-type": "set" + }, "limits": { "additionalProperties": { "allOf": [ @@ -8313,6 +8395,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -8695,6 +8782,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -9033,6 +9125,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__admissionregistration.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__admissionregistration.k8s.io__v1_openapi.json index 45edef2a57a..6ddf6336767 100644 --- a/api/openapi-spec/v3/apis__admissionregistration.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__admissionregistration.k8s.io__v1_openapi.json @@ -843,6 +843,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -1220,6 +1225,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1558,6 +1568,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__admissionregistration.k8s.io__v1alpha1_openapi.json b/api/openapi-spec/v3/apis__admissionregistration.k8s.io__v1alpha1_openapi.json index 6404dd61fb1..f2b45107774 100644 --- a/api/openapi-spec/v3/apis__admissionregistration.k8s.io__v1alpha1_openapi.json +++ b/api/openapi-spec/v3/apis__admissionregistration.k8s.io__v1alpha1_openapi.json @@ -796,6 +796,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -1173,6 +1178,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1511,6 +1521,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__apiextensions.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__apiextensions.k8s.io__v1_openapi.json index 9460074e423..74a002f00f7 100644 --- a/api/openapi-spec/v3/apis__apiextensions.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__apiextensions.k8s.io__v1_openapi.json @@ -1228,6 +1228,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -1548,6 +1553,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1886,6 +1896,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__apps__v1_openapi.json b/api/openapi-spec/v3/apis__apps__v1_openapi.json index 8fc4e23c2d4..2470ce7169d 100644 --- a/api/openapi-spec/v3/apis__apps__v1_openapi.json +++ b/api/openapi-spec/v3/apis__apps__v1_openapi.json @@ -1571,6 +1571,20 @@ ], "type": "object" }, + "io.k8s.api.core.v1.ClaimSource": { + "description": "ClaimSource describes a reference to a ResourceClaim.\n\nExactly one of these fields should be set. Consumers of this type must treat an empty object as if it has an unknown value.", + "properties": { + "resourceClaimName": { + "description": "ResourceClaimName is the name of a ResourceClaim object in the same namespace as this pod.", + "type": "string" + }, + "resourceClaimTemplateName": { + "description": "ResourceClaimTemplateName is the name of a ResourceClaimTemplate object in the same namespace as this pod.\n\nThe template will be used to create a new ResourceClaim, which will be bound to this pod. When this pod is deleted, the ResourceClaim will also be deleted. The name of the ResourceClaim will be -, where is the PodResourceClaim.Name. Pod validation will reject the pod if the concatenated name is not valid for a ResourceClaim (e.g. too long).\n\nAn existing ResourceClaim with that name that is not owned by the pod will not be used for the pod to avoid using an unrelated resource by mistake. Scheduling and pod startup are then blocked until the unrelated ResourceClaim is removed.\n\nThis field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim.", + "type": "string" + } + }, + "type": "object" + }, "io.k8s.api.core.v1.ConfigMapEnvSource": { "description": "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables.", "properties": { @@ -3311,6 +3325,29 @@ ], "type": "object" }, + "io.k8s.api.core.v1.PodResourceClaim": { + "description": "PodResourceClaim references exactly one ResourceClaim through a ClaimSource. It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name.", + "properties": { + "name": { + "default": "", + "description": "Name uniquely identifies this resource claim inside the pod. This must be a DNS_LABEL.", + "type": "string" + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.ClaimSource" + } + ], + "default": {}, + "description": "Source describes where to find the ResourceClaim." + } + }, + "required": [ + "name" + ], + "type": "object" + }, "io.k8s.api.core.v1.PodSchedulingGate": { "description": "PodSchedulingGate is associated to a Pod to guard its scheduling.", "properties": { @@ -3583,6 +3620,24 @@ }, "type": "array" }, + "resourceClaims": { + "description": "ResourceClaims defines which ResourceClaims must be allocated and reserved before the Pod is allowed to start. The resources will be made available to those containers which consume them by name.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.PodResourceClaim" + } + ], + "default": {} + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "name" + ], + "x-kubernetes-list-type": "map", + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge,retainKeys" + }, "restartPolicy": { "description": "Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy\n\n", "type": "string" @@ -3946,6 +4001,20 @@ ], "type": "object" }, + "io.k8s.api.core.v1.ResourceClaim": { + "description": "ResourceClaim references one entry in PodSpec.ResourceClaims.", + "properties": { + "name": { + "default": "", + "description": "Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, "io.k8s.api.core.v1.ResourceFieldSelector": { "description": "ResourceFieldSelector represents container resources (cpu, memory) and their output format", "properties": { @@ -3977,6 +4046,19 @@ "io.k8s.api.core.v1.ResourceRequirements": { "description": "ResourceRequirements describes the compute resource requirements.", "properties": { + "claims": { + "description": "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.ResourceClaim" + } + ], + "default": {} + }, + "type": "array", + "x-kubernetes-list-type": "set" + }, "limits": { "additionalProperties": { "allOf": [ @@ -5330,6 +5412,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -5707,6 +5794,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -6045,6 +6137,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__autoscaling__v1_openapi.json b/api/openapi-spec/v3/apis__autoscaling__v1_openapi.json index cea1c247f94..bdb9cf7a802 100644 --- a/api/openapi-spec/v3/apis__autoscaling__v1_openapi.json +++ b/api/openapi-spec/v3/apis__autoscaling__v1_openapi.json @@ -598,6 +598,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -918,6 +923,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1256,6 +1266,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__autoscaling__v2_openapi.json b/api/openapi-spec/v3/apis__autoscaling__v2_openapi.json index 187cd0df789..7d9e3aaa303 100644 --- a/api/openapi-spec/v3/apis__autoscaling__v2_openapi.json +++ b/api/openapi-spec/v3/apis__autoscaling__v2_openapi.json @@ -1251,6 +1251,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -1628,6 +1633,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1966,6 +1976,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__batch__v1_openapi.json b/api/openapi-spec/v3/apis__batch__v1_openapi.json index 6ead130646c..2c52f2d7782 100644 --- a/api/openapi-spec/v3/apis__batch__v1_openapi.json +++ b/api/openapi-spec/v3/apis__batch__v1_openapi.json @@ -862,6 +862,20 @@ ], "type": "object" }, + "io.k8s.api.core.v1.ClaimSource": { + "description": "ClaimSource describes a reference to a ResourceClaim.\n\nExactly one of these fields should be set. Consumers of this type must treat an empty object as if it has an unknown value.", + "properties": { + "resourceClaimName": { + "description": "ResourceClaimName is the name of a ResourceClaim object in the same namespace as this pod.", + "type": "string" + }, + "resourceClaimTemplateName": { + "description": "ResourceClaimTemplateName is the name of a ResourceClaimTemplate object in the same namespace as this pod.\n\nThe template will be used to create a new ResourceClaim, which will be bound to this pod. When this pod is deleted, the ResourceClaim will also be deleted. The name of the ResourceClaim will be -, where is the PodResourceClaim.Name. Pod validation will reject the pod if the concatenated name is not valid for a ResourceClaim (e.g. too long).\n\nAn existing ResourceClaim with that name that is not owned by the pod will not be used for the pod to avoid using an unrelated resource by mistake. Scheduling and pod startup are then blocked until the unrelated ResourceClaim is removed.\n\nThis field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim.", + "type": "string" + } + }, + "type": "object" + }, "io.k8s.api.core.v1.ConfigMapEnvSource": { "description": "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables.", "properties": { @@ -2485,6 +2499,29 @@ ], "type": "object" }, + "io.k8s.api.core.v1.PodResourceClaim": { + "description": "PodResourceClaim references exactly one ResourceClaim through a ClaimSource. It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name.", + "properties": { + "name": { + "default": "", + "description": "Name uniquely identifies this resource claim inside the pod. This must be a DNS_LABEL.", + "type": "string" + }, + "source": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.ClaimSource" + } + ], + "default": {}, + "description": "Source describes where to find the ResourceClaim." + } + }, + "required": [ + "name" + ], + "type": "object" + }, "io.k8s.api.core.v1.PodSchedulingGate": { "description": "PodSchedulingGate is associated to a Pod to guard its scheduling.", "properties": { @@ -2757,6 +2794,24 @@ }, "type": "array" }, + "resourceClaims": { + "description": "ResourceClaims defines which ResourceClaims must be allocated and reserved before the Pod is allowed to start. The resources will be made available to those containers which consume them by name.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.PodResourceClaim" + } + ], + "default": {} + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "name" + ], + "x-kubernetes-list-type": "map", + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge,retainKeys" + }, "restartPolicy": { "description": "Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy\n\n", "type": "string" @@ -3120,6 +3175,20 @@ ], "type": "object" }, + "io.k8s.api.core.v1.ResourceClaim": { + "description": "ResourceClaim references one entry in PodSpec.ResourceClaims.", + "properties": { + "name": { + "default": "", + "description": "Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, "io.k8s.api.core.v1.ResourceFieldSelector": { "description": "ResourceFieldSelector represents container resources (cpu, memory) and their output format", "properties": { @@ -3151,6 +3220,19 @@ "io.k8s.api.core.v1.ResourceRequirements": { "description": "ResourceRequirements describes the compute resource requirements.", "properties": { + "claims": { + "description": "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.ResourceClaim" + } + ], + "default": {} + }, + "type": "array", + "x-kubernetes-list-type": "set" + }, "limits": { "additionalProperties": { "allOf": [ @@ -4504,6 +4586,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -4881,6 +4968,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -5219,6 +5311,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__certificates.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__certificates.k8s.io__v1_openapi.json index f8cf2c78fae..4557012d847 100644 --- a/api/openapi-spec/v3/apis__certificates.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__certificates.k8s.io__v1_openapi.json @@ -636,6 +636,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -956,6 +961,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1294,6 +1304,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__coordination.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__coordination.k8s.io__v1_openapi.json index f22a600aaa8..dde271d1708 100644 --- a/api/openapi-spec/v3/apis__coordination.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__coordination.k8s.io__v1_openapi.json @@ -525,6 +525,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -850,6 +855,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1188,6 +1198,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__discovery.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__discovery.k8s.io__v1_openapi.json index f89dacf19fc..10aec5a29d1 100644 --- a/api/openapi-spec/v3/apis__discovery.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__discovery.k8s.io__v1_openapi.json @@ -688,6 +688,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -1008,6 +1013,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1346,6 +1356,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__events.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__events.k8s.io__v1_openapi.json index e3475b0e143..bc97105c138 100644 --- a/api/openapi-spec/v3/apis__events.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__events.k8s.io__v1_openapi.json @@ -647,6 +647,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -972,6 +977,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1310,6 +1320,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__flowcontrol.apiserver.k8s.io__v1beta2_openapi.json b/api/openapi-spec/v3/apis__flowcontrol.apiserver.k8s.io__v1beta2_openapi.json index 3c4d0501e4e..67deee60989 100644 --- a/api/openapi-spec/v3/apis__flowcontrol.apiserver.k8s.io__v1beta2_openapi.json +++ b/api/openapi-spec/v3/apis__flowcontrol.apiserver.k8s.io__v1beta2_openapi.json @@ -1108,6 +1108,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -1428,6 +1433,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1766,6 +1776,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__flowcontrol.apiserver.k8s.io__v1beta3_openapi.json b/api/openapi-spec/v3/apis__flowcontrol.apiserver.k8s.io__v1beta3_openapi.json index 401b089bb64..a4d8884c8b1 100644 --- a/api/openapi-spec/v3/apis__flowcontrol.apiserver.k8s.io__v1beta3_openapi.json +++ b/api/openapi-spec/v3/apis__flowcontrol.apiserver.k8s.io__v1beta3_openapi.json @@ -1112,6 +1112,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -1432,6 +1437,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1770,6 +1780,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__internal.apiserver.k8s.io__v1alpha1_openapi.json b/api/openapi-spec/v3/apis__internal.apiserver.k8s.io__v1alpha1_openapi.json index 3a95dfa98ba..514b700d09a 100644 --- a/api/openapi-spec/v3/apis__internal.apiserver.k8s.io__v1alpha1_openapi.json +++ b/api/openapi-spec/v3/apis__internal.apiserver.k8s.io__v1alpha1_openapi.json @@ -615,6 +615,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -935,6 +940,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1273,6 +1283,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__networking.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__networking.k8s.io__v1_openapi.json index 67a6053041c..78d68024697 100644 --- a/api/openapi-spec/v3/apis__networking.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__networking.k8s.io__v1_openapi.json @@ -1276,6 +1276,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -1653,6 +1658,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1991,6 +2001,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__networking.k8s.io__v1alpha1_openapi.json b/api/openapi-spec/v3/apis__networking.k8s.io__v1alpha1_openapi.json index b434c89a4eb..ff8510286c7 100644 --- a/api/openapi-spec/v3/apis__networking.k8s.io__v1alpha1_openapi.json +++ b/api/openapi-spec/v3/apis__networking.k8s.io__v1alpha1_openapi.json @@ -603,6 +603,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -923,6 +928,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1261,6 +1271,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__node.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__node.k8s.io__v1_openapi.json index b6f0fe8a9b0..f0dfa26a82a 100644 --- a/api/openapi-spec/v3/apis__node.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__node.k8s.io__v1_openapi.json @@ -588,6 +588,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -908,6 +913,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1246,6 +1256,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__policy__v1_openapi.json b/api/openapi-spec/v3/apis__policy__v1_openapi.json index 23d42824210..fc8f9134fbf 100644 --- a/api/openapi-spec/v3/apis__policy__v1_openapi.json +++ b/api/openapi-spec/v3/apis__policy__v1_openapi.json @@ -651,6 +651,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -1028,6 +1033,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1366,6 +1376,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__rbac.authorization.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__rbac.authorization.k8s.io__v1_openapi.json index 9e5a9310ae8..ad8e436ebce 100644 --- a/api/openapi-spec/v3/apis__rbac.authorization.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__rbac.authorization.k8s.io__v1_openapi.json @@ -908,6 +908,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -1285,6 +1290,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1623,6 +1633,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__resource.k8s.io__v1alpha1_openapi.json b/api/openapi-spec/v3/apis__resource.k8s.io__v1alpha1_openapi.json new file mode 100644 index 00000000000..a615604dcca --- /dev/null +++ b/api/openapi-spec/v3/apis__resource.k8s.io__v1alpha1_openapi.json @@ -0,0 +1,7761 @@ +{ + "components": { + "schemas": { + "io.k8s.api.core.v1.NodeSelector": { + "description": "A node selector represents the union of the results of one or more label queries over a set of nodes; that is, it represents the OR of the selectors represented by the node selector terms.", + "properties": { + "nodeSelectorTerms": { + "description": "Required. A list of node selector terms. The terms are ORed.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.NodeSelectorTerm" + } + ], + "default": {} + }, + "type": "array" + } + }, + "required": [ + "nodeSelectorTerms" + ], + "type": "object", + "x-kubernetes-map-type": "atomic" + }, + "io.k8s.api.core.v1.NodeSelectorRequirement": { + "description": "A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values.", + "properties": { + "key": { + "default": "", + "description": "The label key that the selector applies to.", + "type": "string" + }, + "operator": { + "default": "", + "description": "Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.\n\n", + "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": { + "default": "", + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object" + }, + "io.k8s.api.core.v1.NodeSelectorTerm": { + "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": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.NodeSelectorRequirement" + } + ], + "default": {} + }, + "type": "array" + }, + "matchFields": { + "description": "A list of node selector requirements by node's fields.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.NodeSelectorRequirement" + } + ], + "default": {} + }, + "type": "array" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic" + }, + "io.k8s.api.resource.v1alpha1.AllocationResult": { + "description": "AllocationResult contains attributed of an allocated resource.", + "properties": { + "availableOnNodes": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.NodeSelector" + } + ], + "description": "This field will get set by the resource driver after it has allocated the resource driver to inform the scheduler where it can schedule Pods using the ResourceClaim.\n\nSetting this field is optional. If null, the resource is available everywhere." + }, + "resourceHandle": { + "description": "ResourceHandle contains arbitrary data returned by the driver after a successful allocation. This is opaque for Kubernetes. Driver documentation may explain to users how to interpret this data if needed.\n\nThe maximum size of this field is 16KiB. This may get increased in the future, but not reduced.", + "type": "string" + }, + "shareable": { + "description": "Shareable determines whether the resource supports more than one consumer at a time.", + "type": "boolean" + } + }, + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.PodScheduling": { + "description": "PodScheduling objects hold information that is needed to schedule a Pod with ResourceClaims that use \"WaitForFirstConsumer\" allocation mode.\n\nThis is an alpha type and requires enabling the DynamicResourceAllocation feature gate.", + "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": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + } + ], + "default": {}, + "description": "Standard object metadata" + }, + "spec": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodSchedulingSpec" + } + ], + "default": {}, + "description": "Spec describes where resources for the Pod are needed." + }, + "status": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodSchedulingStatus" + } + ], + "default": {}, + "description": "Status describes where resources for the Pod can be allocated." + } + }, + "required": [ + "spec" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.PodSchedulingList": { + "description": "PodSchedulingList is a collection of Pod scheduling objects.", + "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" + }, + "items": { + "description": "Items is the list of PodScheduling objects.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + ], + "default": {} + }, + "type": "array" + }, + "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": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + ], + "default": {}, + "description": "Standard list metadata" + } + }, + "required": [ + "items" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "PodSchedulingList", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.PodSchedulingSpec": { + "description": "PodSchedulingSpec describes where resources for the Pod are needed.", + "properties": { + "potentialNodes": { + "description": "PotentialNodes lists nodes where the Pod might be able to run.\n\nThe size of this field is limited to 128. This is large enough for many clusters. Larger clusters may need more attempts to find a node that suits all pending resources. This may get increased in the future, but not reduced.", + "items": { + "default": "", + "type": "string" + }, + "type": "array", + "x-kubernetes-list-type": "set" + }, + "selectedNode": { + "description": "SelectedNode is the node for which allocation of ResourceClaims that are referenced by the Pod and that use \"WaitForFirstConsumer\" allocation is to be attempted.", + "type": "string" + } + }, + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.PodSchedulingStatus": { + "description": "PodSchedulingStatus describes where resources for the Pod can be allocated.", + "properties": { + "resourceClaims": { + "description": "ResourceClaims describes resource availability for each pod.spec.resourceClaim entry where the corresponding ResourceClaim uses \"WaitForFirstConsumer\" allocation mode.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimSchedulingStatus" + } + ], + "default": {} + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "name" + ], + "x-kubernetes-list-type": "map" + } + }, + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClaim": { + "description": "ResourceClaim describes which resources are needed by a resource consumer. Its status tracks whether the resource has been allocated and what the resulting attributes are.\n\nThis is an alpha type and requires enabling the DynamicResourceAllocation feature gate.", + "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": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + } + ], + "default": {}, + "description": "Standard object metadata" + }, + "spec": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimSpec" + } + ], + "default": {}, + "description": "Spec describes the desired attributes of a resource that then needs to be allocated. It can only be set once when creating the ResourceClaim." + }, + "status": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimStatus" + } + ], + "default": {}, + "description": "Status describes whether the resource is available and with which attributes." + } + }, + "required": [ + "spec" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimConsumerReference": { + "description": "ResourceClaimConsumerReference contains enough information to let you locate the consumer of a ResourceClaim. The user must be a resource in the same namespace as the ResourceClaim.", + "properties": { + "apiGroup": { + "description": "APIGroup is the group for the resource being referenced. It is empty for the core API. This matches the group in the APIVersion that is used when creating the resources.", + "type": "string" + }, + "name": { + "default": "", + "description": "Name is the name of resource being referenced.", + "type": "string" + }, + "resource": { + "default": "", + "description": "Resource is the type of resource being referenced, for example \"pods\".", + "type": "string" + }, + "uid": { + "default": "", + "description": "UID identifies exactly one incarnation of the resource.", + "type": "string" + } + }, + "required": [ + "resource", + "name", + "uid" + ], + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimList": { + "description": "ResourceClaimList is a collection of claims.", + "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" + }, + "items": { + "description": "Items is the list of resource claims.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + ], + "default": {} + }, + "type": "array" + }, + "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": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + ], + "default": {}, + "description": "Standard list metadata" + } + }, + "required": [ + "items" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "ResourceClaimList", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimParametersReference": { + "description": "ResourceClaimParametersReference contains enough information to let you locate the parameters for a ResourceClaim. The object must be in the same namespace as the ResourceClaim.", + "properties": { + "apiGroup": { + "description": "APIGroup is the group for the resource being referenced. It is empty for the core API. This matches the group in the APIVersion that is used when creating the resources.", + "type": "string" + }, + "kind": { + "default": "", + "description": "Kind is the type of resource being referenced. This is the same value as in the parameter object's metadata, for example \"ConfigMap\".", + "type": "string" + }, + "name": { + "default": "", + "description": "Name is the name of resource being referenced.", + "type": "string" + } + }, + "required": [ + "kind", + "name" + ], + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimSchedulingStatus": { + "description": "ResourceClaimSchedulingStatus contains information about one particular ResourceClaim with \"WaitForFirstConsumer\" allocation mode.", + "properties": { + "name": { + "description": "Name matches the pod.spec.resourceClaims[*].Name field.", + "type": "string" + }, + "unsuitableNodes": { + "description": "UnsuitableNodes lists nodes that the ResourceClaim cannot be allocated for.\n\nThe size of this field is limited to 128, the same as for PodSchedulingSpec.PotentialNodes. This may get increased in the future, but not reduced.", + "items": { + "default": "", + "type": "string" + }, + "type": "array", + "x-kubernetes-list-type": "set" + } + }, + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimSpec": { + "description": "ResourceClaimSpec defines how a resource is to be allocated.", + "properties": { + "allocationMode": { + "description": "Allocation can start immediately or when a Pod wants to use the resource. \"WaitForFirstConsumer\" is the default.", + "type": "string" + }, + "parametersRef": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimParametersReference" + } + ], + "description": "ParametersRef references a separate object with arbitrary parameters that will be used by the driver when allocating a resource for the claim.\n\nThe object must be in the same namespace as the ResourceClaim." + }, + "resourceClassName": { + "default": "", + "description": "ResourceClassName references the driver and additional parameters via the name of a ResourceClass that was created as part of the driver deployment.", + "type": "string" + } + }, + "required": [ + "resourceClassName" + ], + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimStatus": { + "description": "ResourceClaimStatus tracks whether the resource has been allocated and what the resulting attributes are.", + "properties": { + "allocation": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.AllocationResult" + } + ], + "description": "Allocation is set by the resource driver once a resource has been allocated successfully. If this is not specified, the resource is not yet allocated." + }, + "deallocationRequested": { + "description": "DeallocationRequested indicates that a ResourceClaim is to be deallocated.\n\nThe driver then must deallocate this claim and reset the field together with clearing the Allocation field.\n\nWhile DeallocationRequested is set, no new consumers may be added to ReservedFor.", + "type": "boolean" + }, + "driverName": { + "description": "DriverName is a copy of the driver name from the ResourceClass at the time when allocation started.", + "type": "string" + }, + "reservedFor": { + "description": "ReservedFor indicates which entities are currently allowed to use the claim. A Pod which references a ResourceClaim which is not reserved for that Pod will not be started.\n\nThere can be at most 32 such reservations. This may get increased in the future, but not reduced.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimConsumerReference" + } + ], + "default": {} + }, + "type": "array", + "x-kubernetes-list-type": "set" + } + }, + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimTemplate": { + "description": "ResourceClaimTemplate is used to produce ResourceClaim objects.", + "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": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + } + ], + "default": {}, + "description": "Standard object metadata" + }, + "spec": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateSpec" + } + ], + "default": {}, + "description": "Describes the ResourceClaim that is to be generated.\n\nThis field is immutable. A ResourceClaim will get created by the control plane for a Pod when needed and then not get updated anymore." + } + }, + "required": [ + "spec" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList": { + "description": "ResourceClaimTemplateList is a collection of claim templates.", + "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" + }, + "items": { + "description": "Items is the list of resource claim templates.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + ], + "default": {} + }, + "type": "array" + }, + "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": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + ], + "default": {}, + "description": "Standard list metadata" + } + }, + "required": [ + "items" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplateList", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.ResourceClaimTemplateSpec": { + "description": "ResourceClaimTemplateSpec contains the metadata and fields for a ResourceClaim.", + "properties": { + "metadata": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + } + ], + "default": {}, + "description": "ObjectMeta may contain labels and annotations that will be copied into the PVC when creating it. No other fields are allowed and will be rejected during validation." + }, + "spec": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimSpec" + } + ], + "default": {}, + "description": "Spec for the ResourceClaim. The entire content is copied unchanged into the ResourceClaim that gets created from this template. The same fields as in a ResourceClaim are also valid here." + } + }, + "required": [ + "spec" + ], + "type": "object" + }, + "io.k8s.api.resource.v1alpha1.ResourceClass": { + "description": "ResourceClass is used by administrators to influence how resources are allocated.\n\nThis is an alpha type and requires enabling the DynamicResourceAllocation feature gate.", + "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" + }, + "driverName": { + "default": "", + "description": "DriverName defines the name of the dynamic resource driver that is used for allocation of a ResourceClaim that uses this class.\n\nResource drivers have a unique name in forward domain order (acme.example.com).", + "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": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + } + ], + "default": {}, + "description": "Standard object metadata" + }, + "parametersRef": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClassParametersReference" + } + ], + "description": "ParametersRef references an arbitrary separate object that may hold parameters that will be used by the driver when allocating a resource that uses this class. A dynamic resource driver can distinguish between parameters stored here and and those stored in ResourceClaimSpec." + }, + "suitableNodes": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.NodeSelector" + } + ], + "description": "Only nodes matching the selector will be considered by the scheduler when trying to find a Node that fits a Pod when that Pod uses a ResourceClaim that has not been allocated yet.\n\nSetting this field is optional. If null, all nodes are candidates." + } + }, + "required": [ + "driverName" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.ResourceClassList": { + "description": "ResourceClassList is a collection of classes.", + "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" + }, + "items": { + "description": "Items is the list of resource classes.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + ], + "default": {} + }, + "type": "array" + }, + "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": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + ], + "default": {}, + "description": "Standard list metadata" + } + }, + "required": [ + "items" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "resource.k8s.io", + "kind": "ResourceClassList", + "version": "v1alpha1" + } + ] + }, + "io.k8s.api.resource.v1alpha1.ResourceClassParametersReference": { + "description": "ResourceClassParametersReference contains enough information to let you locate the parameters for a ResourceClass.", + "properties": { + "apiGroup": { + "description": "APIGroup is the group for the resource being referenced. It is empty for the core API. This matches the group in the APIVersion that is used when creating the resources.", + "type": "string" + }, + "kind": { + "default": "", + "description": "Kind is the type of resource being referenced. This is the same value as in the parameter object's metadata.", + "type": "string" + }, + "name": { + "default": "", + "description": "Name is the name of resource being referenced.", + "type": "string" + }, + "namespace": { + "description": "Namespace that contains the referenced resource. Must be empty for cluster-scoped resources and non-empty for namespaced resources.", + "type": "string" + } + }, + "required": [ + "kind", + "name" + ], + "type": "object" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.APIResource": { + "description": "APIResource specifies the name of a resource and whether it is namespaced.", + "properties": { + "categories": { + "description": "categories is a list of the grouped resources this resource belongs to (e.g. 'all')", + "items": { + "default": "", + "type": "string" + }, + "type": "array" + }, + "group": { + "description": "group is the preferred group of the resource. Empty implies the group of the containing resource list. For subresources, this may have a different value, for example: Scale\".", + "type": "string" + }, + "kind": { + "default": "", + "description": "kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')", + "type": "string" + }, + "name": { + "default": "", + "description": "name is the plural name of the resource.", + "type": "string" + }, + "namespaced": { + "default": false, + "description": "namespaced indicates if a resource is namespaced or not.", + "type": "boolean" + }, + "shortNames": { + "description": "shortNames is a list of suggested short names of the resource.", + "items": { + "default": "", + "type": "string" + }, + "type": "array" + }, + "singularName": { + "default": "", + "description": "singularName is the singular name of the resource. This allows clients to handle plural and singular opaquely. The singularName is more correct for reporting status on a single item and both singular and plural are allowed from the kubectl CLI interface.", + "type": "string" + }, + "storageVersionHash": { + "description": "The hash value of the storage version, the version this resource is converted to when written to the data store. Value must be treated as opaque by clients. Only equality comparison on the value is valid. This is an alpha feature and may change or be removed in the future. The field is populated by the apiserver only if the StorageVersionHash feature gate is enabled. This field will remain optional even if it graduates.", + "type": "string" + }, + "verbs": { + "description": "verbs is a list of supported kube verbs (this includes get, list, watch, create, update, patch, delete, deletecollection, and proxy)", + "items": { + "default": "", + "type": "string" + }, + "type": "array" + }, + "version": { + "description": "version is the preferred version of the resource. Empty implies the version of the containing resource list For subresources, this may have a different value, for example: v1 (while inside a v1beta1 version of the core resource's group)\".", + "type": "string" + } + }, + "required": [ + "name", + "singularName", + "namespaced", + "kind", + "verbs" + ], + "type": "object" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList": { + "description": "APIResourceList is a list of APIResource, it is used to expose the name of the resources supported in a specific group and version, and if the resource is namespaced.", + "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" + }, + "groupVersion": { + "default": "", + "description": "groupVersion is the group and version this APIResourceList is for.", + "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" + }, + "resources": { + "description": "resources contains the name of the resources and if they are namespaced.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.APIResource" + } + ], + "default": {} + }, + "type": "array" + } + }, + "required": [ + "groupVersion", + "resources" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "APIResourceList", + "version": "v1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions": { + "description": "DeleteOptions may be provided when deleting an API object.", + "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" + }, + "dryRun": { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "items": { + "default": "", + "type": "string" + }, + "type": "array" + }, + "gracePeriodSeconds": { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "format": "int64", + "type": "integer" + }, + "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" + }, + "orphanDependents": { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "type": "boolean" + }, + "preconditions": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Preconditions" + } + ], + "description": "Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be returned." + }, + "propagationPolicy": { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "type": "string" + } + }, + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "admission.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "admission.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "admissionregistration.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "admissionregistration.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "admissionregistration.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "apiextensions.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "apiextensions.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "apiregistration.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "apiregistration.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "apps", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "apps", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "apps", + "kind": "DeleteOptions", + "version": "v1beta2" + }, + { + "group": "authentication.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "authentication.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "authentication.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "autoscaling", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "autoscaling", + "kind": "DeleteOptions", + "version": "v2" + }, + { + "group": "autoscaling", + "kind": "DeleteOptions", + "version": "v2beta1" + }, + { + "group": "autoscaling", + "kind": "DeleteOptions", + "version": "v2beta2" + }, + { + "group": "batch", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "batch", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "certificates.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "certificates.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "coordination.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "coordination.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "discovery.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "discovery.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "events.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "events.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "extensions", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "flowcontrol.apiserver.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "flowcontrol.apiserver.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "flowcontrol.apiserver.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta2" + }, + { + "group": "flowcontrol.apiserver.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta3" + }, + { + "group": "imagepolicy.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "internal.apiserver.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "networking.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "networking.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "networking.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "node.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "node.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "node.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "policy", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "policy", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "scheduling.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "scheduling.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "scheduling.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + }, + { + "group": "storage.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, + { + "group": "storage.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, + { + "group": "storage.k8s.io", + "kind": "DeleteOptions", + "version": "v1beta1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.FieldsV1": { + "description": "FieldsV1 stores a set of fields in a data structure like a Trie, in JSON format.\n\nEach key is either a '.' representing the field itself, and will always map to an empty set, or a string representing a sub-field or item. The string will follow one of these four formats: 'f:', where is the name of a field in a struct, or key in a map 'v:', where is the exact json formatted value of a list item 'i:', where is position of a item in a list 'k:', where is a map of a list item's key fields to their unique values If a key maps to an empty Fields value, the field that key represents is part of the set.\n\nThe exact format is defined in sigs.k8s.io/structured-merge-diff", + "type": "object" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta": { + "description": "ListMeta describes metadata that synthetic resources must have, including lists and various status objects. A resource may have only one of {ObjectMeta, ListMeta}.", + "properties": { + "continue": { + "description": "continue may be set if the user set a limit on the number of items returned, and indicates that the server has more data available. The value is opaque and may be used to issue another request to the endpoint that served this list to retrieve the next set of available objects. Continuing a consistent list may not be possible if the server configuration has changed or more than a few minutes have passed. The resourceVersion field returned when using this continue value will be identical to the value in the first response, unless you have received this token from an error message.", + "type": "string" + }, + "remainingItemCount": { + "description": "remainingItemCount is the number of subsequent items in the list which are not included in this list response. If the list request contained label or field selectors, then the number of remaining items is unknown and the field will be left unset and omitted during serialization. If the list is complete (either because it is not chunking or because this is the last chunk), then there are no more remaining items and this field will be left unset and omitted during serialization. Servers older than v1.15 do not set this field. The intended use of the remainingItemCount is *estimating* the size of a collection. Clients should not rely on the remainingItemCount to be set or to be exact.", + "format": "int64", + "type": "integer" + }, + "resourceVersion": { + "description": "String that identifies the server's internal version of this object that can be used by clients to determine when objects have changed. Value must be treated as opaque by clients and passed unmodified back to the server. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency", + "type": "string" + }, + "selfLink": { + "description": "Deprecated: selfLink is a legacy read-only field that is no longer populated by the system.", + "type": "string" + } + }, + "type": "object" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.ManagedFieldsEntry": { + "description": "ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of the resource that the fieldset applies to.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the version of this resource that this field set applies to. The format is \"group/version\" just like the top-level APIVersion field. It is necessary to track the version of a field set because it cannot be automatically converted.", + "type": "string" + }, + "fieldsType": { + "description": "FieldsType is the discriminator for the different fields format and version. There is currently only one possible value: \"FieldsV1\"", + "type": "string" + }, + "fieldsV1": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.FieldsV1" + } + ], + "description": "FieldsV1 holds the first JSON version format as described in the \"FieldsV1\" type." + }, + "manager": { + "description": "Manager is an identifier of the workflow managing these fields.", + "type": "string" + }, + "operation": { + "description": "Operation is the type of operation which lead to this ManagedFieldsEntry being created. The only valid values for this field are 'Apply' and 'Update'.", + "type": "string" + }, + "subresource": { + "description": "Subresource is the name of the subresource used to update that object, or empty string if the object was updated through the main resource. The value of this field is used to distinguish between managers, even if they share the same name. For example, a status update will be distinct from a regular update using the same manager name. Note that the APIVersion field is not related to the Subresource field and it always corresponds to the version of the main resource.", + "type": "string" + }, + "time": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + } + ], + "description": "Time is the timestamp of when the ManagedFields entry was added. The timestamp will also be updated if a field is added, the manager changes any of the owned fields value or removes a field. The timestamp does not update when a field is removed from the entry because another manager took it over." + } + }, + "type": "object" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta": { + "description": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.", + "properties": { + "annotations": { + "additionalProperties": { + "default": "", + "type": "string" + }, + "description": "Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations", + "type": "object" + }, + "creationTimestamp": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + } + ], + "default": {}, + "description": "CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata" + }, + "deletionGracePeriodSeconds": { + "description": "Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only.", + "format": "int64", + "type": "integer" + }, + "deletionTimestamp": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + } + ], + "description": "DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field, once the finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. Once the deletionTimestamp is set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.\n\nPopulated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata" + }, + "finalizers": { + "description": "Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed. Finalizers may be processed and removed in any order. Order is NOT enforced because it introduces significant risk of stuck finalizers. finalizers is a shared field, any actor with permission can reorder it. If the finalizer list is processed in order, then this can lead to a situation in which the component responsible for the first finalizer in the list is waiting for a signal (field value, external system, or other) produced by a component responsible for a finalizer later in the list, resulting in a deadlock. Without enforced ordering finalizers are free to order amongst themselves and are not vulnerable to ordering changes in the list.", + "items": { + "default": "", + "type": "string" + }, + "type": "array", + "x-kubernetes-patch-strategy": "merge" + }, + "generateName": { + "description": "GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.\n\nIf this field is specified and the generated name exists, the server will return a 409.\n\nApplied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency", + "type": "string" + }, + "generation": { + "description": "A sequence number representing a specific generation of the desired state. Populated by the system. Read-only.", + "format": "int64", + "type": "integer" + }, + "labels": { + "additionalProperties": { + "default": "", + "type": "string" + }, + "description": "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels", + "type": "object" + }, + "managedFields": { + "description": "ManagedFields maps workflow-id and version to the set of fields that are managed by that workflow. This is mostly for internal housekeeping, and users typically shouldn't need to set or understand this field. A workflow can be the user's name, a controller's name, or the name of a specific apply path like \"ci-cd\". The set of fields is always in the version that the workflow used when modifying the object.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ManagedFieldsEntry" + } + ], + "default": {} + }, + "type": "array" + }, + "name": { + "description": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names", + "type": "string" + }, + "namespace": { + "description": "Namespace defines the space within which each name must be unique. An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.\n\nMust be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces", + "type": "string" + }, + "ownerReferences": { + "description": "List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference" + } + ], + "default": {} + }, + "type": "array", + "x-kubernetes-patch-merge-key": "uid", + "x-kubernetes-patch-strategy": "merge" + }, + "resourceVersion": { + "description": "An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.\n\nPopulated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency", + "type": "string" + }, + "selfLink": { + "description": "Deprecated: selfLink is a legacy read-only field that is no longer populated by the system.", + "type": "string" + }, + "uid": { + "description": "UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.\n\nPopulated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids", + "type": "string" + } + }, + "type": "object" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.OwnerReference": { + "description": "OwnerReference contains enough information to let you identify an owning object. An owning object must be in the same namespace as the dependent, or be cluster-scoped, so there is no namespace field.", + "properties": { + "apiVersion": { + "default": "", + "description": "API version of the referent.", + "type": "string" + }, + "blockOwnerDeletion": { + "description": "If true, AND if the owner has the \"foregroundDeletion\" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. See https://kubernetes.io/docs/concepts/architecture/garbage-collection/#foreground-deletion for how the garbage collector interacts with this field and enforces the foreground deletion. Defaults to false. To set this field, a user needs \"delete\" permission of the owner, otherwise 422 (Unprocessable Entity) will be returned.", + "type": "boolean" + }, + "controller": { + "description": "If true, this reference points to the managing controller.", + "type": "boolean" + }, + "kind": { + "default": "", + "description": "Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "name": { + "default": "", + "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", + "type": "string" + }, + "uid": { + "default": "", + "description": "UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids", + "type": "string" + } + }, + "required": [ + "apiVersion", + "kind", + "name", + "uid" + ], + "type": "object", + "x-kubernetes-map-type": "atomic" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Patch": { + "description": "Patch is provided to give a concrete name and type to the Kubernetes PATCH request body.", + "type": "object" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Preconditions": { + "description": "Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.", + "properties": { + "resourceVersion": { + "description": "Specifies the target ResourceVersion", + "type": "string" + }, + "uid": { + "description": "Specifies the target UID.", + "type": "string" + } + }, + "type": "object" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Status": { + "description": "Status is a return value for calls that don't return other objects.", + "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" + }, + "code": { + "description": "Suggested HTTP return code for this status, 0 if not set.", + "format": "int32", + "type": "integer" + }, + "details": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.StatusDetails" + } + ], + "description": "Extended data associated with the reason. Each reason may define its own extended details. This field is optional and the data returned is not guaranteed to conform to any schema except that defined by the reason type." + }, + "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" + }, + "message": { + "description": "A human-readable description of the status of this operation.", + "type": "string" + }, + "metadata": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + ], + "default": {}, + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds" + }, + "reason": { + "description": "A machine-readable description of why this operation is in the \"Failure\" status. If this value is empty there is no information available. A Reason clarifies an HTTP status code but does not override it.", + "type": "string" + }, + "status": { + "description": "Status of the operation. One of: \"Success\" or \"Failure\". More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status", + "type": "string" + } + }, + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "Status", + "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.StatusCause": { + "description": "StatusCause provides more information about an api.Status failure, including cases when multiple errors are encountered.", + "properties": { + "field": { + "description": "The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional.\n\nExamples:\n \"name\" - the field \"name\" on the current resource\n \"items[0].name\" - the field \"name\" on the first array entry in \"items\"", + "type": "string" + }, + "message": { + "description": "A human-readable description of the cause of the error. This field may be presented as-is to a reader.", + "type": "string" + }, + "reason": { + "description": "A machine-readable description of the cause of the error. If this value is empty there is no information available.", + "type": "string" + } + }, + "type": "object" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.StatusDetails": { + "description": "StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined.", + "properties": { + "causes": { + "description": "The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.StatusCause" + } + ], + "default": {} + }, + "type": "array" + }, + "group": { + "description": "The group attribute of the resource associated with the status StatusReason.", + "type": "string" + }, + "kind": { + "description": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "name": { + "description": "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described).", + "type": "string" + }, + "retryAfterSeconds": { + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.", + "format": "int32", + "type": "integer" + }, + "uid": { + "description": "UID of the resource. (when there is a single resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids", + "type": "string" + } + }, + "type": "object" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.Time": { + "description": "Time is a wrapper around time.Time which supports correct marshaling to YAML and JSON. Wrappers are provided for many of the factory methods that the time package offers.", + "format": "date-time", + "type": "string" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent": { + "description": "Event represents a single event to a watched resource.", + "properties": { + "object": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.runtime.RawExtension" + } + ], + "default": {}, + "description": "Object is:\n * If Type is Added or Modified: the new state of the object.\n * If Type is Deleted: the state of the object immediately before deletion.\n * If Type is Error: *Status is recommended; other types may make sense\n depending on context." + }, + "type": { + "default": "", + "type": "string" + } + }, + "required": [ + "type", + "object" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "admission.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "admission.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "admissionregistration.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "admissionregistration.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "admissionregistration.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "apiextensions.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "apiextensions.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "apiregistration.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "apiregistration.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "apps", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "apps", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "apps", + "kind": "WatchEvent", + "version": "v1beta2" + }, + { + "group": "authentication.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "authentication.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "authentication.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "autoscaling", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "autoscaling", + "kind": "WatchEvent", + "version": "v2" + }, + { + "group": "autoscaling", + "kind": "WatchEvent", + "version": "v2beta1" + }, + { + "group": "autoscaling", + "kind": "WatchEvent", + "version": "v2beta2" + }, + { + "group": "batch", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "batch", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "certificates.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "certificates.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "coordination.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "coordination.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "discovery.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "discovery.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "events.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "events.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "extensions", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "flowcontrol.apiserver.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "flowcontrol.apiserver.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "flowcontrol.apiserver.k8s.io", + "kind": "WatchEvent", + "version": "v1beta2" + }, + { + "group": "flowcontrol.apiserver.k8s.io", + "kind": "WatchEvent", + "version": "v1beta3" + }, + { + "group": "imagepolicy.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "internal.apiserver.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "networking.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "networking.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "networking.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "node.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "node.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "node.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "policy", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "policy", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "rbac.authorization.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "scheduling.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "scheduling.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "scheduling.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + }, + { + "group": "storage.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, + { + "group": "storage.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, + { + "group": "storage.k8s.io", + "kind": "WatchEvent", + "version": "v1beta1" + } + ] + }, + "io.k8s.apimachinery.pkg.runtime.RawExtension": { + "description": "RawExtension is used to hold extensions in external versions.\n\nTo use this, make a field which has RawExtension as its type in your external, versioned struct, and Object in your internal struct. You also need to register your various plugin types.\n\n// Internal package:\n\n\ttype MyAPIObject struct {\n\t\truntime.TypeMeta `json:\",inline\"`\n\t\tMyPlugin runtime.Object `json:\"myPlugin\"`\n\t}\n\n\ttype PluginA struct {\n\t\tAOption string `json:\"aOption\"`\n\t}\n\n// External package:\n\n\ttype MyAPIObject struct {\n\t\truntime.TypeMeta `json:\",inline\"`\n\t\tMyPlugin runtime.RawExtension `json:\"myPlugin\"`\n\t}\n\n\ttype PluginA struct {\n\t\tAOption string `json:\"aOption\"`\n\t}\n\n// On the wire, the JSON will look something like this:\n\n\t{\n\t\t\"kind\":\"MyAPIObject\",\n\t\t\"apiVersion\":\"v1\",\n\t\t\"myPlugin\": {\n\t\t\t\"kind\":\"PluginA\",\n\t\t\t\"aOption\":\"foo\",\n\t\t},\n\t}\n\nSo what happens? Decode first uses json or yaml to unmarshal the serialized data into your external MyAPIObject. That causes the raw JSON to be stored, but not unpacked. The next step is to copy (using pkg/conversion) into the internal struct. The runtime package's DefaultScheme has conversion functions installed which will unpack the JSON stored in RawExtension, turning it into the correct object type, and storing it in the Object. (TODO: In the case where the object is of an unknown type, a runtime.Unknown object will be created and stored.)", + "type": "object" + } + }, + "securitySchemes": { + "BearerToken": { + "description": "Bearer Token authentication", + "in": "header", + "name": "authorization", + "type": "apiKey" + } + } + }, + "info": { + "title": "Kubernetes", + "version": "unversioned" + }, + "openapi": "3.0.0", + "paths": { + "/apis/resource.k8s.io/v1alpha1/": { + "get": { + "description": "get available resources", + "operationId": "getResourceV1alpha1APIResources", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ] + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/podschedulings": { + "delete": { + "description": "delete collection of PodScheduling", + "operationId": "deleteResourceV1alpha1CollectionNamespacedPodScheduling", + "parameters": [ + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "deletecollection", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "get": { + "description": "list or watch objects of kind PodScheduling", + "operationId": "listResourceV1alpha1NamespacedPodScheduling", + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodSchedulingList" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodSchedulingList" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodSchedulingList" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodSchedulingList" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodSchedulingList" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "post": { + "description": "create a PodScheduling", + "operationId": "createResourceV1alpha1NamespacedPodScheduling", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "Created" + }, + "202": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "Accepted" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "post", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/podschedulings/{name}": { + "delete": { + "description": "delete a PodScheduling", + "operationId": "deleteResourceV1alpha1NamespacedPodScheduling", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "OK" + }, + "202": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "Accepted" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "delete", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "get": { + "description": "read the specified PodScheduling", + "operationId": "readResourceV1alpha1NamespacedPodScheduling", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "name of the PodScheduling", + "in": "path", + "name": "name", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "patch": { + "description": "partially update the specified PodScheduling", + "operationId": "patchResourceV1alpha1NamespacedPodScheduling", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "in": "query", + "name": "force", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "application/apply-patch+yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/json-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/merge-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/strategic-merge-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "Created" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "put": { + "description": "replace the specified PodScheduling", + "operationId": "replaceResourceV1alpha1NamespacedPodScheduling", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "Created" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/podschedulings/{name}/status": { + "get": { + "description": "read status of the specified PodScheduling", + "operationId": "readResourceV1alpha1NamespacedPodSchedulingStatus", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "name of the PodScheduling", + "in": "path", + "name": "name", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "patch": { + "description": "partially update status of the specified PodScheduling", + "operationId": "patchResourceV1alpha1NamespacedPodSchedulingStatus", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "in": "query", + "name": "force", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "application/apply-patch+yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/json-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/merge-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/strategic-merge-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "Created" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "put": { + "description": "replace status of the specified PodScheduling", + "operationId": "replaceResourceV1alpha1NamespacedPodSchedulingStatus", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodScheduling" + } + } + }, + "description": "Created" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/resourceclaims": { + "delete": { + "description": "delete collection of ResourceClaim", + "operationId": "deleteResourceV1alpha1CollectionNamespacedResourceClaim", + "parameters": [ + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "deletecollection", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "get": { + "description": "list or watch objects of kind ResourceClaim", + "operationId": "listResourceV1alpha1NamespacedResourceClaim", + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimList" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimList" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimList" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimList" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimList" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "post": { + "description": "create a ResourceClaim", + "operationId": "createResourceV1alpha1NamespacedResourceClaim", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "Created" + }, + "202": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "Accepted" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "post", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/resourceclaims/{name}": { + "delete": { + "description": "delete a ResourceClaim", + "operationId": "deleteResourceV1alpha1NamespacedResourceClaim", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "OK" + }, + "202": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "Accepted" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "delete", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "get": { + "description": "read the specified ResourceClaim", + "operationId": "readResourceV1alpha1NamespacedResourceClaim", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "name of the ResourceClaim", + "in": "path", + "name": "name", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "patch": { + "description": "partially update the specified ResourceClaim", + "operationId": "patchResourceV1alpha1NamespacedResourceClaim", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "in": "query", + "name": "force", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "application/apply-patch+yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/json-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/merge-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/strategic-merge-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "Created" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "put": { + "description": "replace the specified ResourceClaim", + "operationId": "replaceResourceV1alpha1NamespacedResourceClaim", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "Created" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/resourceclaims/{name}/status": { + "get": { + "description": "read status of the specified ResourceClaim", + "operationId": "readResourceV1alpha1NamespacedResourceClaimStatus", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "name of the ResourceClaim", + "in": "path", + "name": "name", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "patch": { + "description": "partially update status of the specified ResourceClaim", + "operationId": "patchResourceV1alpha1NamespacedResourceClaimStatus", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "in": "query", + "name": "force", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "application/apply-patch+yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/json-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/merge-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/strategic-merge-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "Created" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "put": { + "description": "replace status of the specified ResourceClaim", + "operationId": "replaceResourceV1alpha1NamespacedResourceClaimStatus", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaim" + } + } + }, + "description": "Created" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/resourceclaimtemplates": { + "delete": { + "description": "delete collection of ResourceClaimTemplate", + "operationId": "deleteResourceV1alpha1CollectionNamespacedResourceClaimTemplate", + "parameters": [ + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "deletecollection", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "get": { + "description": "list or watch objects of kind ResourceClaimTemplate", + "operationId": "listResourceV1alpha1NamespacedResourceClaimTemplate", + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "post": { + "description": "create a ResourceClaimTemplate", + "operationId": "createResourceV1alpha1NamespacedResourceClaimTemplate", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + } + }, + "description": "Created" + }, + "202": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + } + }, + "description": "Accepted" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "post", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/namespaces/{namespace}/resourceclaimtemplates/{name}": { + "delete": { + "description": "delete a ResourceClaimTemplate", + "operationId": "deleteResourceV1alpha1NamespacedResourceClaimTemplate", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + } + }, + "description": "OK" + }, + "202": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + } + }, + "description": "Accepted" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "delete", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "get": { + "description": "read the specified ResourceClaimTemplate", + "operationId": "readResourceV1alpha1NamespacedResourceClaimTemplate", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "name of the ResourceClaimTemplate", + "in": "path", + "name": "name", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "patch": { + "description": "partially update the specified ResourceClaimTemplate", + "operationId": "patchResourceV1alpha1NamespacedResourceClaimTemplate", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "in": "query", + "name": "force", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "application/apply-patch+yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/json-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/merge-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/strategic-merge-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + } + }, + "description": "Created" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "put": { + "description": "replace the specified ResourceClaimTemplate", + "operationId": "replaceResourceV1alpha1NamespacedResourceClaimTemplate", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplate" + } + } + }, + "description": "Created" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/podschedulings": { + "get": { + "description": "list or watch objects of kind PodScheduling", + "operationId": "listResourceV1alpha1PodSchedulingForAllNamespaces", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodSchedulingList" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodSchedulingList" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodSchedulingList" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodSchedulingList" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.PodSchedulingList" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/resourceclaims": { + "get": { + "description": "list or watch objects of kind ResourceClaim", + "operationId": "listResourceV1alpha1ResourceClaimForAllNamespaces", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimList" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimList" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimList" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimList" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimList" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/resourceclaimtemplates": { + "get": { + "description": "list or watch objects of kind ResourceClaimTemplate", + "operationId": "listResourceV1alpha1ResourceClaimTemplateForAllNamespaces", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClaimTemplateList" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/resourceclasses": { + "delete": { + "description": "delete collection of ResourceClass", + "operationId": "deleteResourceV1alpha1CollectionResourceClass", + "parameters": [ + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "deletecollection", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "get": { + "description": "list or watch objects of kind ResourceClass", + "operationId": "listResourceV1alpha1ResourceClass", + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClassList" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClassList" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClassList" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClassList" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClassList" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "post": { + "description": "create a ResourceClass", + "operationId": "createResourceV1alpha1ResourceClass", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + } + }, + "description": "Created" + }, + "202": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + } + }, + "description": "Accepted" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "post", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/resourceclasses/{name}": { + "delete": { + "description": "delete a ResourceClass", + "operationId": "deleteResourceV1alpha1ResourceClass", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "in": "query", + "name": "gracePeriodSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "in": "query", + "name": "orphanDependents", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "in": "query", + "name": "propagationPolicy", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + } + }, + "description": "OK" + }, + "202": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + } + }, + "description": "Accepted" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "delete", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "get": { + "description": "read the specified ResourceClass", + "operationId": "readResourceV1alpha1ResourceClass", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "name of the ResourceClass", + "in": "path", + "name": "name", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "patch": { + "description": "partially update the specified ResourceClass", + "operationId": "patchResourceV1alpha1ResourceClass", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "in": "query", + "name": "force", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "application/apply-patch+yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/json-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/merge-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + "application/strategic-merge-patch+json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + } + }, + "description": "Created" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "put": { + "description": "replace the specified ResourceClass", + "operationId": "replaceResourceV1alpha1ResourceClass", + "parameters": [ + { + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "in": "query", + "name": "dryRun", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + "in": "query", + "name": "fieldManager", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields, provided that the `ServerSideFieldValidation` feature gate is also enabled. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23 and is the default behavior when the `ServerSideFieldValidation` feature gate is disabled. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default when the `ServerSideFieldValidation` feature gate is enabled. - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "in": "query", + "name": "fieldValidation", + "schema": { + "type": "string", + "uniqueItems": true + } + } + ], + "requestBody": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + } + }, + "description": "OK" + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.api.resource.v1alpha1.ResourceClass" + } + } + }, + "description": "Created" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + } + }, + "/apis/resource.k8s.io/v1alpha1/watch/namespaces/{namespace}/podschedulings": { + "get": { + "description": "watch individual changes to a list of PodScheduling. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1NamespacedPodSchedulingList", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/namespaces/{namespace}/podschedulings/{name}": { + "get": { + "description": "watch changes to an object of kind PodScheduling. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.", + "operationId": "watchResourceV1alpha1NamespacedPodScheduling", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "name of the PodScheduling", + "in": "path", + "name": "name", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/namespaces/{namespace}/resourceclaims": { + "get": { + "description": "watch individual changes to a list of ResourceClaim. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1NamespacedResourceClaimList", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/namespaces/{namespace}/resourceclaims/{name}": { + "get": { + "description": "watch changes to an object of kind ResourceClaim. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.", + "operationId": "watchResourceV1alpha1NamespacedResourceClaim", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "name of the ResourceClaim", + "in": "path", + "name": "name", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/namespaces/{namespace}/resourceclaimtemplates": { + "get": { + "description": "watch individual changes to a list of ResourceClaimTemplate. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1NamespacedResourceClaimTemplateList", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/namespaces/{namespace}/resourceclaimtemplates/{name}": { + "get": { + "description": "watch changes to an object of kind ResourceClaimTemplate. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.", + "operationId": "watchResourceV1alpha1NamespacedResourceClaimTemplate", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "name of the ResourceClaimTemplate", + "in": "path", + "name": "name", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "object name and auth scope, such as for teams and projects", + "in": "path", + "name": "namespace", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/podschedulings": { + "get": { + "description": "watch individual changes to a list of PodScheduling. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1PodSchedulingListForAllNamespaces", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "PodScheduling", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/resourceclaims": { + "get": { + "description": "watch individual changes to a list of ResourceClaim. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1ResourceClaimListForAllNamespaces", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaim", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/resourceclaimtemplates": { + "get": { + "description": "watch individual changes to a list of ResourceClaimTemplate. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1ResourceClaimTemplateListForAllNamespaces", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClaimTemplate", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/resourceclasses": { + "get": { + "description": "watch individual changes to a list of ResourceClass. deprecated: use the 'watch' parameter with a list operation instead.", + "operationId": "watchResourceV1alpha1ResourceClassList", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + }, + "/apis/resource.k8s.io/v1alpha1/watch/resourceclasses/{name}": { + "get": { + "description": "watch changes to an object of kind ResourceClass. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.", + "operationId": "watchResourceV1alpha1ResourceClass", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/json;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/vnd.kubernetes.protobuf;stream=watch": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource_v1alpha1" + ], + "x-kubernetes-action": "watch", + "x-kubernetes-group-version-kind": { + "group": "resource.k8s.io", + "kind": "ResourceClass", + "version": "v1alpha1" + } + }, + "parameters": [ + { + "description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + "in": "query", + "name": "allowWatchBookmarks", + "schema": { + "type": "boolean", + "uniqueItems": true + } + }, + { + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "in": "query", + "name": "continue", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "in": "query", + "name": "fieldSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "in": "query", + "name": "labelSelector", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "in": "query", + "name": "limit", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "name of the ResourceClass", + "in": "path", + "name": "name", + "required": true, + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "If 'true', then the output is pretty printed.", + "in": "query", + "name": "pretty", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersion", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + "in": "query", + "name": "resourceVersionMatch", + "schema": { + "type": "string", + "uniqueItems": true + } + }, + { + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "in": "query", + "name": "timeoutSeconds", + "schema": { + "type": "integer", + "uniqueItems": true + } + }, + { + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "in": "query", + "name": "watch", + "schema": { + "type": "boolean", + "uniqueItems": true + } + } + ] + } + } +} diff --git a/api/openapi-spec/v3/apis__resource.k8s.io_openapi.json b/api/openapi-spec/v3/apis__resource.k8s.io_openapi.json new file mode 100644 index 00000000000..3065bf68bd0 --- /dev/null +++ b/api/openapi-spec/v3/apis__resource.k8s.io_openapi.json @@ -0,0 +1,158 @@ +{ + "components": { + "schemas": { + "io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup": { + "description": "APIGroup contains the name, the supported versions, and the preferred version of a group.", + "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" + }, + "name": { + "default": "", + "description": "name is the name of the group.", + "type": "string" + }, + "preferredVersion": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery" + } + ], + "default": {}, + "description": "preferredVersion is the version preferred by the API server, which probably is the storage version." + }, + "serverAddressByClientCIDRs": { + "description": "a map of client CIDR to server address that is serving this group. This is to help clients reach servers in the most network-efficient way possible. Clients can use the appropriate server address as per the CIDR that they match. In case of multiple matches, clients should use the longest matching CIDR. The server returns only those CIDRs that it thinks that the client can match. For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR" + } + ], + "default": {} + }, + "type": "array" + }, + "versions": { + "description": "versions are the versions supported in this group.", + "items": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery" + } + ], + "default": {} + }, + "type": "array" + } + }, + "required": [ + "name", + "versions" + ], + "type": "object", + "x-kubernetes-group-version-kind": [ + { + "group": "", + "kind": "APIGroup", + "version": "v1" + } + ] + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.GroupVersionForDiscovery": { + "description": "GroupVersion contains the \"group/version\" and \"version\" string of a version. It is made a struct to keep extensibility.", + "properties": { + "groupVersion": { + "default": "", + "description": "groupVersion specifies the API group and version in the form \"group/version\"", + "type": "string" + }, + "version": { + "default": "", + "description": "version specifies the version in the form of \"version\". This is to save the clients the trouble of splitting the GroupVersion.", + "type": "string" + } + }, + "required": [ + "groupVersion", + "version" + ], + "type": "object" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR": { + "description": "ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match.", + "properties": { + "clientCIDR": { + "default": "", + "description": "The CIDR with which clients can match their IP to figure out the server address that they should use.", + "type": "string" + }, + "serverAddress": { + "default": "", + "description": "Address of this server, suitable for a client that matches the above CIDR. This can be a hostname, hostname:port, IP or IP:port.", + "type": "string" + } + }, + "required": [ + "clientCIDR", + "serverAddress" + ], + "type": "object" + } + }, + "securitySchemes": { + "BearerToken": { + "description": "Bearer Token authentication", + "in": "header", + "name": "authorization", + "type": "apiKey" + } + } + }, + "info": { + "title": "Kubernetes", + "version": "unversioned" + }, + "openapi": "3.0.0", + "paths": { + "/apis/resource.k8s.io/": { + "get": { + "description": "get information of a group", + "operationId": "getResourceAPIGroup", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup" + } + }, + "application/vnd.kubernetes.protobuf": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup" + } + }, + "application/yaml": { + "schema": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup" + } + } + }, + "description": "OK" + }, + "401": { + "description": "Unauthorized" + } + }, + "tags": [ + "resource" + ] + } + } + } +} diff --git a/api/openapi-spec/v3/apis__scheduling.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__scheduling.k8s.io__v1_openapi.json index c79b657b417..e65ef216862 100644 --- a/api/openapi-spec/v3/apis__scheduling.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__scheduling.k8s.io__v1_openapi.json @@ -501,6 +501,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -821,6 +826,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1159,6 +1169,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__storage.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__storage.k8s.io__v1_openapi.json index f04f6ecb89b..e7b22a3731a 100644 --- a/api/openapi-spec/v3/apis__storage.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__storage.k8s.io__v1_openapi.json @@ -2340,6 +2340,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -2717,6 +2722,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -3055,6 +3065,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/api/openapi-spec/v3/apis__storage.k8s.io__v1beta1_openapi.json b/api/openapi-spec/v3/apis__storage.k8s.io__v1beta1_openapi.json index d529363461f..13c45d646ea 100644 --- a/api/openapi-spec/v3/apis__storage.k8s.io__v1beta1_openapi.json +++ b/api/openapi-spec/v3/apis__storage.k8s.io__v1beta1_openapi.json @@ -527,6 +527,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "DeleteOptions", @@ -904,6 +909,11 @@ "group": "", "kind": "Status", "version": "v1" + }, + { + "group": "resource.k8s.io", + "kind": "Status", + "version": "v1alpha1" } ] }, @@ -1242,6 +1252,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "resource.k8s.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "scheduling.k8s.io", "kind": "WatchEvent", diff --git a/cmd/kube-apiserver/app/aggregator.go b/cmd/kube-apiserver/app/aggregator.go index 72ba55df6b9..82fc15cf091 100644 --- a/cmd/kube-apiserver/app/aggregator.go +++ b/cmd/kube-apiserver/app/aggregator.go @@ -283,6 +283,7 @@ var apiVersionPriorities = map[schema.GroupVersion]priority{ {Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta1"}: {group: 16100, version: 12}, {Group: "flowcontrol.apiserver.k8s.io", Version: "v1alpha1"}: {group: 16100, version: 9}, {Group: "internal.apiserver.k8s.io", Version: "v1alpha1"}: {group: 16000, version: 9}, + {Group: "resource.k8s.io", Version: "v1alpha1"}: {group: 15900, version: 9}, // Append a new group to the end of the list if unsure. // You can use min(existing group)-100 as the initial value for a group. // Version can be set to 9 (to have space around) for a new group. diff --git a/cmd/kube-controller-manager/app/controllermanager.go b/cmd/kube-controller-manager/app/controllermanager.go index fb6546e58d0..bb33636c016 100644 --- a/cmd/kube-controller-manager/app/controllermanager.go +++ b/cmd/kube-controller-manager/app/controllermanager.go @@ -475,6 +475,9 @@ func NewControllerInitializers(loopMode ControllerLoopMode) map[string]InitFunc utilfeature.DefaultFeatureGate.Enabled(genericfeatures.StorageVersionAPI) { register("storage-version-gc", startStorageVersionGCController) } + if utilfeature.DefaultFeatureGate.Enabled(kubefeatures.DynamicResourceAllocation) { + controllers["resource-claim-controller"] = startResourceClaimController + } return controllers } diff --git a/cmd/kube-controller-manager/app/core.go b/cmd/kube-controller-manager/app/core.go index 616d4d25200..cdcbd854b67 100644 --- a/cmd/kube-controller-manager/app/core.go +++ b/cmd/kube-controller-manager/app/core.go @@ -54,6 +54,7 @@ import ( lifecyclecontroller "k8s.io/kubernetes/pkg/controller/nodelifecycle" "k8s.io/kubernetes/pkg/controller/podgc" replicationcontroller "k8s.io/kubernetes/pkg/controller/replication" + "k8s.io/kubernetes/pkg/controller/resourceclaim" resourcequotacontroller "k8s.io/kubernetes/pkg/controller/resourcequota" serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount" "k8s.io/kubernetes/pkg/controller/storageversiongc" @@ -357,6 +358,21 @@ func startEphemeralVolumeController(ctx context.Context, controllerContext Contr return nil, true, nil } +const defaultResourceClaimControllerWorkers = 10 + +func startResourceClaimController(ctx context.Context, controllerContext ControllerContext) (controller.Interface, bool, error) { + ephemeralController, err := resourceclaim.NewController( + controllerContext.ClientBuilder.ClientOrDie("resource-claim-controller"), + controllerContext.InformerFactory.Core().V1().Pods(), + controllerContext.InformerFactory.Resource().V1alpha1().ResourceClaims(), + controllerContext.InformerFactory.Resource().V1alpha1().ResourceClaimTemplates()) + if err != nil { + return nil, true, fmt.Errorf("failed to start ephemeral volume controller: %v", err) + } + go ephemeralController.Run(ctx, defaultResourceClaimControllerWorkers) + return nil, true, nil +} + func startEndpointController(ctx context.Context, controllerCtx ControllerContext) (controller.Interface, bool, error) { go endpointcontroller.NewEndpointController( controllerCtx.InformerFactory.Core().V1().Pods(), diff --git a/cmd/kube-controller-manager/app/import_known_versions.go b/cmd/kube-controller-manager/app/import_known_versions.go index a76ce309970..5b3dfa7cd71 100644 --- a/cmd/kube-controller-manager/app/import_known_versions.go +++ b/cmd/kube-controller-manager/app/import_known_versions.go @@ -33,6 +33,7 @@ import ( _ "k8s.io/kubernetes/pkg/apis/extensions/install" _ "k8s.io/kubernetes/pkg/apis/policy/install" _ "k8s.io/kubernetes/pkg/apis/rbac/install" + _ "k8s.io/kubernetes/pkg/apis/resource/install" _ "k8s.io/kubernetes/pkg/apis/scheduling/install" _ "k8s.io/kubernetes/pkg/apis/storage/install" ) diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index c4c42cc8802..3899df80ee3 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -41,7 +41,7 @@ import ( cadvisorapi "github.com/google/cadvisor/info/v1" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" otelsdkresource "go.opentelemetry.io/otel/sdk/resource" - "go.opentelemetry.io/otel/semconv/v1.12.0" + semconv "go.opentelemetry.io/otel/semconv/v1.12.0" oteltrace "go.opentelemetry.io/otel/trace" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -756,7 +756,9 @@ func run(ctx context.Context, s *options.KubeletServer, kubeDeps *kubelet.Depend ExperimentalTopologyManagerPolicyOptions: topologyManagerPolicyOptions, }, s.FailSwapOn, - kubeDeps.Recorder) + kubeDeps.Recorder, + kubeDeps.KubeClient, + ) if err != nil { return err diff --git a/go.mod b/go.mod index cd36227f931..adc2204b99c 100644 --- a/go.mod +++ b/go.mod @@ -107,6 +107,7 @@ require ( k8s.io/controller-manager v0.0.0 k8s.io/cri-api v0.0.0 k8s.io/csi-translation-lib v0.0.0 + k8s.io/dynamic-resource-allocation v0.0.0 k8s.io/gengo v0.0.0-20220902162205-c0856e24416d k8s.io/klog/v2 v2.80.1 k8s.io/kms v0.0.0 @@ -261,6 +262,7 @@ replace ( k8s.io/controller-manager => ./staging/src/k8s.io/controller-manager k8s.io/cri-api => ./staging/src/k8s.io/cri-api k8s.io/csi-translation-lib => ./staging/src/k8s.io/csi-translation-lib + k8s.io/dynamic-resource-allocation => ./staging/src/k8s.io/dynamic-resource-allocation k8s.io/kms => ./staging/src/k8s.io/kms k8s.io/kube-aggregator => ./staging/src/k8s.io/kube-aggregator k8s.io/kube-controller-manager => ./staging/src/k8s.io/kube-controller-manager diff --git a/hack/lib/init.sh b/hack/lib/init.sh index 51e3d1db195..17f69c91c53 100755 --- a/hack/lib/init.sh +++ b/hack/lib/init.sh @@ -89,6 +89,7 @@ coordination.k8s.io/v1beta1 \ coordination.k8s.io/v1 \ discovery.k8s.io/v1 \ discovery.k8s.io/v1beta1 \ +resource.k8s.io/v1alpha1 \ extensions/v1beta1 \ events.k8s.io/v1 \ events.k8s.io/v1beta1 \ diff --git a/hack/logcheck.conf b/hack/logcheck.conf index 3ec1cf4f9a5..db678525c05 100644 --- a/hack/logcheck.conf +++ b/hack/logcheck.conf @@ -25,6 +25,8 @@ structured k8s.io/kubernetes/pkg/scheduler/.* # Packages matched here do not have to be listed above because # "contextual" implies "structured". # TODO next: contextual k8s.io/kubernetes/pkg/scheduler/.* +contextual k8s.io/kubernetes/test/e2e/dra/.* +contextual k8s.io/dynamic-resource-allocation/.* # As long as contextual logging is alpha or beta, all WithName, WithValues, # NewContext calls have to go through klog. Once it is GA, we can lift diff --git a/hack/make-rules/update.sh b/hack/make-rules/update.sh index 25f8dc3be3a..447fc6624c8 100755 --- a/hack/make-rules/update.sh +++ b/hack/make-rules/update.sh @@ -40,6 +40,7 @@ BASH_TARGETS=" update-codegen update-generated-runtime update-generated-device-plugin + update-generated-dynamic-resource-allocation update-generated-api-compatibility-data update-generated-docs update-generated-swagger-docs diff --git a/hack/unwanted-dependencies.json b/hack/unwanted-dependencies.json index c9610a3f8a1..e3e0b4399fb 100644 --- a/hack/unwanted-dependencies.json +++ b/hack/unwanted-dependencies.json @@ -9,6 +9,8 @@ "github.com/go-openapi/strfmt": "use k8s.io/kube-openapi/pkg/validation/strfmt instead", "github.com/go-openapi/validate": "use k8s.io/kube-openapi/pkg/validation/validate instead", "github.com/hashicorp/consul": "MPL license not in CNCF allowlist", + "github.com/hashicorp/errwrap": "MPL license not in CNCF allowlist", + "github.com/hashicorp/go-multierror": "MPL license not in CNCF allowlist", "github.com/hashicorp/golang-lru": "MPL license not in CNCF allowlist", "github.com/hashicorp/hcl": "MPL license not in CNCF allowlist", "github.com/influxdata/influxdb1-client": "", @@ -17,7 +19,10 @@ "github.com/onsi/ginkgo": "Ginkgo has been migrated to V2, refer to #109111", "github.com/spf13/viper": "refer to #102598", "go.mongodb.org/mongo-driver": "", + "gopkg.in/fsnotify.v1": "obsolete, use github.com/fsnotify/fsnotify", "k8s.io/klog": "we have switched to klog v2, so avoid klog v1", + "github.com/mndrix/tap-go": "unmaintained", + "github.com/xeipuuv/gojsonschema": "unmaintained", "rsc.io/quote": "refer to #102833", "rsc.io/sampler": "refer to #102833" } diff --git a/hack/update-generated-dynamic-resource-allocation-dockerized.sh b/hack/update-generated-dynamic-resource-allocation-dockerized.sh new file mode 100755 index 00000000000..ad9f75f114d --- /dev/null +++ b/hack/update-generated-dynamic-resource-allocation-dockerized.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# Copyright 2017 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script generates `*/api.pb.go` from the protobuf file `*/api.proto`. +# Example: +# kube::protoc::generate_proto "${DYNAMIC_RESOURCE_ALLOCATION_ALPHA}" + +set -o errexit +set -o nounset +set -o pipefail + +KUBE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../" && pwd -P)" +DYNAMIC_RESOURCE_ALLOCATION_V1ALPHA1="${KUBE_ROOT}/staging/src/k8s.io/kubelet/pkg/apis/dra/v1alpha1/" + +source "${KUBE_ROOT}/hack/lib/protoc.sh" +kube::protoc::generate_proto "${DYNAMIC_RESOURCE_ALLOCATION_V1ALPHA1}" diff --git a/hack/update-generated-dynamic-resource-allocation.sh b/hack/update-generated-dynamic-resource-allocation.sh new file mode 100755 index 00000000000..d20db5edb5e --- /dev/null +++ b/hack/update-generated-dynamic-resource-allocation.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# Copyright 2017 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. + +# NOTE: All output from this script needs to be copied back to the calling +# source tree. This is managed in kube::build::copy_output in build/common.sh. +# If the output set is changed update that function. + +"${KUBE_ROOT}/build/run.sh" hack/update-generated-dynamic-resource-allocation-dockerized.sh "$@" diff --git a/hack/verify-generated-dynamic-resource-allocation.sh b/hack/verify-generated-dynamic-resource-allocation.sh new file mode 100755 index 00000000000..3f38cbf5671 --- /dev/null +++ b/hack/verify-generated-dynamic-resource-allocation.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Copyright 2022 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script checks whether updating of device plugin API is needed or not. We +# should run `hack/update-generated-dynamic-resource-allocation.sh` if device plugin API is +# out of date. +# Usage: `hack/verify-generated-dynamic-resource-allocation.sh`. + +set -o errexit +set -o nounset +set -o pipefail + +KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +ERROR="Dynamic resource allocation kubelet plugin api is out of date. Please run hack/update-generated-dynamic-resource-allocation.sh" +DYNAMIC_RESOURCE_ALLOCATION_V1ALPHA1="${KUBE_ROOT}/staging/src/k8s.io/kubelet/pkg/apis/dra/v1alpha1/" + +source "${KUBE_ROOT}/hack/lib/protoc.sh" +kube::golang::setup_env + +function cleanup { + rm -rf "${DYNAMIC_RESOURCE_ALLOCATION_V1ALPHA1}/_tmp/" +} + +trap cleanup EXIT + +mkdir -p "${DYNAMIC_RESOURCE_ALLOCATION_V1ALPHA1}/_tmp" +cp "${DYNAMIC_RESOURCE_ALLOCATION_V1ALPHA1}/api.pb.go" "${DYNAMIC_RESOURCE_ALLOCATION_V1ALPHA1}/_tmp/" + +KUBE_VERBOSE=3 "${KUBE_ROOT}/hack/update-generated-dynamic-resource-allocation.sh" +kube::protoc::diff "${DYNAMIC_RESOURCE_ALLOCATION_V1ALPHA1}/api.pb.go" "${DYNAMIC_RESOURCE_ALLOCATION_V1ALPHA1}/_tmp/api.pb.go" "${ERROR}" +echo "Generated dynamic resource allocation kubelet plugin alpha api is up to date." diff --git a/pkg/api/pod/util.go b/pkg/api/pod/util.go index 61d74bf177c..c99a8e34f30 100644 --- a/pkg/api/pod/util.go +++ b/pkg/api/pod/util.go @@ -550,6 +550,42 @@ func dropDisabledFields( dropDisabledTopologySpreadConstraintsFields(podSpec, oldPodSpec) dropDisabledNodeInclusionPolicyFields(podSpec, oldPodSpec) dropDisabledMatchLabelKeysField(podSpec, oldPodSpec) + dropDisabledDynamicResourceAllocationFields(podSpec, oldPodSpec) +} + +// dropDisabledDynamicResourceAllocationFields removes pod claim references from +// container specs and pod-level resource claims unless they are already used +// by the old pod spec. +func dropDisabledDynamicResourceAllocationFields(podSpec, oldPodSpec *api.PodSpec) { + if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) && !dynamicResourceAllocationInUse(oldPodSpec) { + dropResourceClaimRequests(podSpec.Containers) + dropResourceClaimRequests(podSpec.InitContainers) + dropEphemeralResourceClaimRequests(podSpec.EphemeralContainers) + podSpec.ResourceClaims = nil + } +} + +func dynamicResourceAllocationInUse(podSpec *api.PodSpec) bool { + if podSpec == nil { + return false + } + + // We only need to check this field because the containers cannot have + // resource requirements entries for claims without a corresponding + // entry at the pod spec level. + return len(podSpec.ResourceClaims) > 0 +} + +func dropResourceClaimRequests(containers []api.Container) { + for i := range containers { + containers[i].Resources.Claims = nil + } +} + +func dropEphemeralResourceClaimRequests(containers []api.EphemeralContainer) { + for i := range containers { + containers[i].Resources.Claims = nil + } } // dropDisabledTopologySpreadConstraintsFields removes disabled fields from PodSpec related diff --git a/pkg/api/pod/util_test.go b/pkg/api/pod/util_test.go index 1dfef8aa245..0271e1a5271 100644 --- a/pkg/api/pod/util_test.go +++ b/pkg/api/pod/util_test.go @@ -784,6 +784,165 @@ func TestDropAppArmor(t *testing.T) { } } +func TestDropDynamicResourceAllocation(t *testing.T) { + resourceClaimName := "external-claim" + + podWithClaims := &api.Pod{ + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Resources: api.ResourceRequirements{ + Claims: []api.ResourceClaim{{Name: "my-claim"}}, + }, + }, + }, + InitContainers: []api.Container{ + { + Resources: api.ResourceRequirements{ + Claims: []api.ResourceClaim{{Name: "my-claim"}}, + }, + }, + }, + EphemeralContainers: []api.EphemeralContainer{ + { + EphemeralContainerCommon: api.EphemeralContainerCommon{ + Resources: api.ResourceRequirements{ + Claims: []api.ResourceClaim{{Name: "my-claim"}}, + }, + }, + }, + }, + ResourceClaims: []api.PodResourceClaim{ + { + Name: "my-claim", + Source: api.ClaimSource{ + ResourceClaimName: &resourceClaimName, + }, + }, + }, + }, + } + podWithoutClaims := &api.Pod{ + Spec: api.PodSpec{ + Containers: []api.Container{{}}, + InitContainers: []api.Container{{}}, + EphemeralContainers: []api.EphemeralContainer{{}}, + }, + } + + var noPod *api.Pod + + testcases := []struct { + description string + enabled bool + oldPod *api.Pod + newPod *api.Pod + wantPod *api.Pod + }{ + { + description: "old with claims / new with claims / disabled", + oldPod: podWithClaims, + newPod: podWithClaims, + wantPod: podWithClaims, + }, + { + description: "old without claims / new with claims / disabled", + oldPod: podWithoutClaims, + newPod: podWithClaims, + wantPod: podWithoutClaims, + }, + { + description: "no old pod/ new with claims / disabled", + oldPod: noPod, + newPod: podWithClaims, + wantPod: podWithoutClaims, + }, + + { + description: "old with claims / new without claims / disabled", + oldPod: podWithClaims, + newPod: podWithoutClaims, + wantPod: podWithoutClaims, + }, + { + description: "old without claims / new without claims / disabled", + oldPod: podWithoutClaims, + newPod: podWithoutClaims, + wantPod: podWithoutClaims, + }, + { + description: "no old pod/ new without claims / disabled", + oldPod: noPod, + newPod: podWithoutClaims, + wantPod: podWithoutClaims, + }, + + { + description: "old with claims / new with claims / enabled", + enabled: true, + oldPod: podWithClaims, + newPod: podWithClaims, + wantPod: podWithClaims, + }, + { + description: "old without claims / new with claims / enabled", + enabled: true, + oldPod: podWithoutClaims, + newPod: podWithClaims, + wantPod: podWithClaims, + }, + { + description: "no old pod/ new with claims / enabled", + enabled: true, + oldPod: noPod, + newPod: podWithClaims, + wantPod: podWithClaims, + }, + + { + description: "old with claims / new without claims / enabled", + enabled: true, + oldPod: podWithClaims, + newPod: podWithoutClaims, + wantPod: podWithoutClaims, + }, + { + description: "old without claims / new without claims / enabled", + enabled: true, + oldPod: podWithoutClaims, + newPod: podWithoutClaims, + wantPod: podWithoutClaims, + }, + { + description: "no old pod/ new without claims / enabled", + enabled: true, + oldPod: noPod, + newPod: podWithoutClaims, + wantPod: podWithoutClaims, + }, + } + + for _, tc := range testcases { + t.Run(tc.description, func(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DynamicResourceAllocation, tc.enabled)() + + oldPod := tc.oldPod.DeepCopy() + newPod := tc.newPod.DeepCopy() + wantPod := tc.wantPod + DropDisabledPodFields(newPod, oldPod) + + // old pod should never be changed + if diff := cmp.Diff(oldPod, tc.oldPod); diff != "" { + t.Errorf("old pod changed: %s", diff) + } + + if diff := cmp.Diff(wantPod, newPod); diff != "" { + t.Errorf("new pod changed (- want, + got): %s", diff) + } + }) + } +} + func TestDropProbeGracePeriod(t *testing.T) { podWithProbeGracePeriod := func() *api.Pod { livenessGracePeriod := int64(10) diff --git a/pkg/api/testing/defaulting_test.go b/pkg/api/testing/defaulting_test.go index cd341e60a72..acafe9aca70 100644 --- a/pkg/api/testing/defaulting_test.go +++ b/pkg/api/testing/defaulting_test.go @@ -139,6 +139,10 @@ func TestDefaulting(t *testing.T) { {Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBindingList"}: {}, {Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "RoleBinding"}: {}, {Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "RoleBindingList"}: {}, + {Group: "resource.k8s.io", Version: "v1alpha1", Kind: "ResourceClaim"}: {}, + {Group: "resource.k8s.io", Version: "v1alpha1", Kind: "ResourceClaimList"}: {}, + {Group: "resource.k8s.io", Version: "v1alpha1", Kind: "ResourceClaimTemplate"}: {}, + {Group: "resource.k8s.io", Version: "v1alpha1", Kind: "ResourceClaimTemplateList"}: {}, {Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "ValidatingAdmissionPolicy"}: {}, {Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "ValidatingAdmissionPolicyList"}: {}, {Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "ValidatingAdmissionPolicyBinding"}: {}, diff --git a/pkg/api/testing/fuzzer.go b/pkg/api/testing/fuzzer.go index e43f0b8ebb6..e2773c78c2e 100644 --- a/pkg/api/testing/fuzzer.go +++ b/pkg/api/testing/fuzzer.go @@ -42,6 +42,7 @@ import ( networkingfuzzer "k8s.io/kubernetes/pkg/apis/networking/fuzzer" policyfuzzer "k8s.io/kubernetes/pkg/apis/policy/fuzzer" rbacfuzzer "k8s.io/kubernetes/pkg/apis/rbac/fuzzer" + resourcefuzzer "k8s.io/kubernetes/pkg/apis/resource/fuzzer" schedulingfuzzer "k8s.io/kubernetes/pkg/apis/scheduling/fuzzer" storagefuzzer "k8s.io/kubernetes/pkg/apis/storage/fuzzer" ) @@ -101,6 +102,7 @@ var FuzzerFuncs = fuzzer.MergeFuzzerFuncs( autoscalingfuzzer.Funcs, rbacfuzzer.Funcs, policyfuzzer.Funcs, + resourcefuzzer.Funcs, certificatesfuzzer.Funcs, admissionregistrationfuzzer.Funcs, storagefuzzer.Funcs, diff --git a/pkg/api/testing/install.go b/pkg/api/testing/install.go index 78b9a1a987e..e596d7e543c 100644 --- a/pkg/api/testing/install.go +++ b/pkg/api/testing/install.go @@ -37,6 +37,7 @@ import ( _ "k8s.io/kubernetes/pkg/apis/node/install" _ "k8s.io/kubernetes/pkg/apis/policy/install" _ "k8s.io/kubernetes/pkg/apis/rbac/install" + _ "k8s.io/kubernetes/pkg/apis/resource/install" _ "k8s.io/kubernetes/pkg/apis/scheduling/install" _ "k8s.io/kubernetes/pkg/apis/storage/install" ) diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go index 0622050a17d..fbbecb00d58 100644 --- a/pkg/apis/core/types.go +++ b/pkg/apis/core/types.go @@ -2185,6 +2185,25 @@ type ResourceRequirements struct { // otherwise to an implementation-defined value // +optional Requests ResourceList + // Claims lists the names of resources, defined in spec.resourceClaims, + // that are used by this container. + // + // This is an alpha field and requires enabling the + // DynamicResourceAllocation feature gate. + // + // This field is immutable. + // + // +featureGate=DynamicResourceAllocation + // +optional + Claims []ResourceClaim +} + +// ResourceClaim references one entry in PodSpec.ResourceClaims. +type ResourceClaim struct { + // Name must match the name of one entry in pod.spec.resourceClaims of + // the Pod where this field is used. It makes that resource available + // inside a container. + Name string } // Container represents a single container that is expected to be run on the host. @@ -3024,12 +3043,68 @@ type PodSpec struct { // - spec.containers[*].securityContext.runAsGroup // +optional OS *PodOS + // SchedulingGates is an opaque list of values that if specified will block scheduling the pod. // More info: https://git.k8s.io/enhancements/keps/sig-scheduling/3521-pod-scheduling-readiness. // // This is an alpha-level feature enabled by PodSchedulingReadiness feature gate. // +optional SchedulingGates []PodSchedulingGate + // ResourceClaims defines which ResourceClaims must be allocated + // and reserved before the Pod is allowed to start. The resources + // will be made available to those containers which consume them + // by name. + // + // This is an alpha field and requires enabling the + // DynamicResourceAllocation feature gate. + // + // This field is immutable. + // + // +featureGate=DynamicResourceAllocation + // +optional + ResourceClaims []PodResourceClaim +} + +// PodResourceClaim references exactly one ResourceClaim through a ClaimSource. +// It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. +// Containers that need access to the ResourceClaim reference it with this name. +type PodResourceClaim struct { + // Name uniquely identifies this resource claim inside the pod. + // This must be a DNS_LABEL. + Name string + + // Source describes where to find the ResourceClaim. + Source ClaimSource +} + +// ClaimSource describes a reference to a ResourceClaim. +// +// Exactly one of these fields should be set. Consumers of this type must +// treat an empty object as if it has an unknown value. +type ClaimSource struct { + // ResourceClaimName is the name of a ResourceClaim object in the same + // namespace as this pod. + ResourceClaimName *string + + // ResourceClaimTemplateName is the name of a ResourceClaimTemplate + // object in the same namespace as this pod. + // + // The template will be used to create a new ResourceClaim, which will + // be bound to this pod. When this pod is deleted, the ResourceClaim + // will also be deleted. The name of the ResourceClaim will be -, where is the + // PodResourceClaim.Name. Pod validation will reject the pod if the + // concatenated name is not valid for a ResourceClaim (e.g. too long). + // + // An existing ResourceClaim with that name that is not owned by the + // pod will not be used for the pod to avoid using an unrelated + // resource by mistake. Scheduling and pod startup are then blocked + // until the unrelated ResourceClaim is removed. + // + // This field is immutable and no changes will be made to the + // corresponding ResourceClaim by the control plane after creating the + // ResourceClaim. + ResourceClaimTemplateName *string } // OSName is the set of OS'es that can be used in OS. diff --git a/pkg/apis/core/v1/zz_generated.conversion.go b/pkg/apis/core/v1/zz_generated.conversion.go index 153441540b1..c27a86783ba 100644 --- a/pkg/apis/core/v1/zz_generated.conversion.go +++ b/pkg/apis/core/v1/zz_generated.conversion.go @@ -192,6 +192,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*v1.ClaimSource)(nil), (*core.ClaimSource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_ClaimSource_To_core_ClaimSource(a.(*v1.ClaimSource), b.(*core.ClaimSource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*core.ClaimSource)(nil), (*v1.ClaimSource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_core_ClaimSource_To_v1_ClaimSource(a.(*core.ClaimSource), b.(*v1.ClaimSource), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*v1.ClientIPConfig)(nil), (*core.ClientIPConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1_ClientIPConfig_To_core_ClientIPConfig(a.(*v1.ClientIPConfig), b.(*core.ClientIPConfig), scope) }); err != nil { @@ -1352,6 +1362,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*v1.PodResourceClaim)(nil), (*core.PodResourceClaim)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_PodResourceClaim_To_core_PodResourceClaim(a.(*v1.PodResourceClaim), b.(*core.PodResourceClaim), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*core.PodResourceClaim)(nil), (*v1.PodResourceClaim)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_core_PodResourceClaim_To_v1_PodResourceClaim(a.(*core.PodResourceClaim), b.(*v1.PodResourceClaim), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*v1.PodSchedulingGate)(nil), (*core.PodSchedulingGate)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1_PodSchedulingGate_To_core_PodSchedulingGate(a.(*v1.PodSchedulingGate), b.(*core.PodSchedulingGate), scope) }); err != nil { @@ -1572,6 +1592,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*v1.ResourceClaim)(nil), (*core.ResourceClaim)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_ResourceClaim_To_core_ResourceClaim(a.(*v1.ResourceClaim), b.(*core.ResourceClaim), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*core.ResourceClaim)(nil), (*v1.ResourceClaim)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_core_ResourceClaim_To_v1_ResourceClaim(a.(*core.ResourceClaim), b.(*v1.ResourceClaim), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*v1.ResourceFieldSelector)(nil), (*core.ResourceFieldSelector)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1_ResourceFieldSelector_To_core_ResourceFieldSelector(a.(*v1.ResourceFieldSelector), b.(*core.ResourceFieldSelector), scope) }); err != nil { @@ -2633,6 +2663,28 @@ func Convert_core_CinderVolumeSource_To_v1_CinderVolumeSource(in *core.CinderVol return autoConvert_core_CinderVolumeSource_To_v1_CinderVolumeSource(in, out, s) } +func autoConvert_v1_ClaimSource_To_core_ClaimSource(in *v1.ClaimSource, out *core.ClaimSource, s conversion.Scope) error { + out.ResourceClaimName = (*string)(unsafe.Pointer(in.ResourceClaimName)) + out.ResourceClaimTemplateName = (*string)(unsafe.Pointer(in.ResourceClaimTemplateName)) + return nil +} + +// Convert_v1_ClaimSource_To_core_ClaimSource is an autogenerated conversion function. +func Convert_v1_ClaimSource_To_core_ClaimSource(in *v1.ClaimSource, out *core.ClaimSource, s conversion.Scope) error { + return autoConvert_v1_ClaimSource_To_core_ClaimSource(in, out, s) +} + +func autoConvert_core_ClaimSource_To_v1_ClaimSource(in *core.ClaimSource, out *v1.ClaimSource, s conversion.Scope) error { + out.ResourceClaimName = (*string)(unsafe.Pointer(in.ResourceClaimName)) + out.ResourceClaimTemplateName = (*string)(unsafe.Pointer(in.ResourceClaimTemplateName)) + return nil +} + +// Convert_core_ClaimSource_To_v1_ClaimSource is an autogenerated conversion function. +func Convert_core_ClaimSource_To_v1_ClaimSource(in *core.ClaimSource, out *v1.ClaimSource, s conversion.Scope) error { + return autoConvert_core_ClaimSource_To_v1_ClaimSource(in, out, s) +} + func autoConvert_v1_ClientIPConfig_To_core_ClientIPConfig(in *v1.ClientIPConfig, out *core.ClientIPConfig, s conversion.Scope) error { out.TimeoutSeconds = (*int32)(unsafe.Pointer(in.TimeoutSeconds)) return nil @@ -6089,6 +6141,32 @@ func Convert_core_PodReadinessGate_To_v1_PodReadinessGate(in *core.PodReadinessG return autoConvert_core_PodReadinessGate_To_v1_PodReadinessGate(in, out, s) } +func autoConvert_v1_PodResourceClaim_To_core_PodResourceClaim(in *v1.PodResourceClaim, out *core.PodResourceClaim, s conversion.Scope) error { + out.Name = in.Name + if err := Convert_v1_ClaimSource_To_core_ClaimSource(&in.Source, &out.Source, s); err != nil { + return err + } + return nil +} + +// Convert_v1_PodResourceClaim_To_core_PodResourceClaim is an autogenerated conversion function. +func Convert_v1_PodResourceClaim_To_core_PodResourceClaim(in *v1.PodResourceClaim, out *core.PodResourceClaim, s conversion.Scope) error { + return autoConvert_v1_PodResourceClaim_To_core_PodResourceClaim(in, out, s) +} + +func autoConvert_core_PodResourceClaim_To_v1_PodResourceClaim(in *core.PodResourceClaim, out *v1.PodResourceClaim, s conversion.Scope) error { + out.Name = in.Name + if err := Convert_core_ClaimSource_To_v1_ClaimSource(&in.Source, &out.Source, s); err != nil { + return err + } + return nil +} + +// Convert_core_PodResourceClaim_To_v1_PodResourceClaim is an autogenerated conversion function. +func Convert_core_PodResourceClaim_To_v1_PodResourceClaim(in *core.PodResourceClaim, out *v1.PodResourceClaim, s conversion.Scope) error { + return autoConvert_core_PodResourceClaim_To_v1_PodResourceClaim(in, out, s) +} + func autoConvert_v1_PodSchedulingGate_To_core_PodSchedulingGate(in *v1.PodSchedulingGate, out *core.PodSchedulingGate, s conversion.Scope) error { out.Name = in.Name return nil @@ -6229,6 +6307,7 @@ func autoConvert_v1_PodSpec_To_core_PodSpec(in *v1.PodSpec, out *core.PodSpec, s out.OS = (*core.PodOS)(unsafe.Pointer(in.OS)) // INFO: in.HostUsers opted out of conversion generation out.SchedulingGates = *(*[]core.PodSchedulingGate)(unsafe.Pointer(&in.SchedulingGates)) + out.ResourceClaims = *(*[]core.PodResourceClaim)(unsafe.Pointer(&in.ResourceClaims)) return nil } @@ -6283,6 +6362,7 @@ func autoConvert_core_PodSpec_To_v1_PodSpec(in *core.PodSpec, out *v1.PodSpec, s out.TopologySpreadConstraints = *(*[]v1.TopologySpreadConstraint)(unsafe.Pointer(&in.TopologySpreadConstraints)) out.OS = (*v1.PodOS)(unsafe.Pointer(in.OS)) out.SchedulingGates = *(*[]v1.PodSchedulingGate)(unsafe.Pointer(&in.SchedulingGates)) + out.ResourceClaims = *(*[]v1.PodResourceClaim)(unsafe.Pointer(&in.ResourceClaims)) return nil } @@ -6947,6 +7027,26 @@ func Convert_core_ReplicationControllerStatus_To_v1_ReplicationControllerStatus( return autoConvert_core_ReplicationControllerStatus_To_v1_ReplicationControllerStatus(in, out, s) } +func autoConvert_v1_ResourceClaim_To_core_ResourceClaim(in *v1.ResourceClaim, out *core.ResourceClaim, s conversion.Scope) error { + out.Name = in.Name + return nil +} + +// Convert_v1_ResourceClaim_To_core_ResourceClaim is an autogenerated conversion function. +func Convert_v1_ResourceClaim_To_core_ResourceClaim(in *v1.ResourceClaim, out *core.ResourceClaim, s conversion.Scope) error { + return autoConvert_v1_ResourceClaim_To_core_ResourceClaim(in, out, s) +} + +func autoConvert_core_ResourceClaim_To_v1_ResourceClaim(in *core.ResourceClaim, out *v1.ResourceClaim, s conversion.Scope) error { + out.Name = in.Name + return nil +} + +// Convert_core_ResourceClaim_To_v1_ResourceClaim is an autogenerated conversion function. +func Convert_core_ResourceClaim_To_v1_ResourceClaim(in *core.ResourceClaim, out *v1.ResourceClaim, s conversion.Scope) error { + return autoConvert_core_ResourceClaim_To_v1_ResourceClaim(in, out, s) +} + func autoConvert_v1_ResourceFieldSelector_To_core_ResourceFieldSelector(in *v1.ResourceFieldSelector, out *core.ResourceFieldSelector, s conversion.Scope) error { out.ContainerName = in.ContainerName out.Resource = in.Resource @@ -7074,6 +7174,7 @@ func Convert_core_ResourceQuotaStatus_To_v1_ResourceQuotaStatus(in *core.Resourc func autoConvert_v1_ResourceRequirements_To_core_ResourceRequirements(in *v1.ResourceRequirements, out *core.ResourceRequirements, s conversion.Scope) error { out.Limits = *(*core.ResourceList)(unsafe.Pointer(&in.Limits)) out.Requests = *(*core.ResourceList)(unsafe.Pointer(&in.Requests)) + out.Claims = *(*[]core.ResourceClaim)(unsafe.Pointer(&in.Claims)) return nil } @@ -7085,6 +7186,7 @@ func Convert_v1_ResourceRequirements_To_core_ResourceRequirements(in *v1.Resourc func autoConvert_core_ResourceRequirements_To_v1_ResourceRequirements(in *core.ResourceRequirements, out *v1.ResourceRequirements, s conversion.Scope) error { out.Limits = *(*v1.ResourceList)(unsafe.Pointer(&in.Limits)) out.Requests = *(*v1.ResourceList)(unsafe.Pointer(&in.Requests)) + out.Claims = *(*[]v1.ResourceClaim)(unsafe.Pointer(&in.Claims)) return nil } diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index 8c5611cec59..d53339863b3 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -309,7 +309,7 @@ func ValidateRuntimeClassName(name string, fldPath *field.Path) field.ErrorList // validateOverhead can be used to check whether the given Overhead is valid. func validateOverhead(overhead core.ResourceList, fldPath *field.Path, opts PodValidationOptions) field.ErrorList { // reuse the ResourceRequirements validation logic - return ValidateResourceRequirements(&core.ResourceRequirements{Limits: overhead}, fldPath, opts) + return ValidateResourceRequirements(&core.ResourceRequirements{Limits: overhead}, nil, fldPath, opts) } // Validates that given value is not negative. @@ -1621,12 +1621,12 @@ func validateEphemeralVolumeSource(ephemeral *core.EphemeralVolumeSource, fldPat // ValidatePersistentVolumeClaimTemplate verifies that the embedded object meta and spec are valid. // Checking of the object data is very minimal because only labels and annotations are used. func ValidatePersistentVolumeClaimTemplate(claimTemplate *core.PersistentVolumeClaimTemplate, fldPath *field.Path, opts PersistentVolumeClaimSpecValidationOptions) field.ErrorList { - allErrs := validatePersistentVolumeClaimTemplateObjectMeta(&claimTemplate.ObjectMeta, fldPath.Child("metadata")) + allErrs := ValidateTemplateObjectMeta(&claimTemplate.ObjectMeta, fldPath.Child("metadata")) allErrs = append(allErrs, ValidatePersistentVolumeClaimSpec(&claimTemplate.Spec, fldPath.Child("spec"), opts)...) return allErrs } -func validatePersistentVolumeClaimTemplateObjectMeta(objMeta *metav1.ObjectMeta, fldPath *field.Path) field.ErrorList { +func ValidateTemplateObjectMeta(objMeta *metav1.ObjectMeta, fldPath *field.Path) field.ErrorList { allErrs := apimachineryvalidation.ValidateAnnotations(objMeta.Annotations, fldPath.Child("annotations")) allErrs = append(allErrs, unversionedvalidation.ValidateLabels(objMeta.Labels, fldPath.Child("labels"))...) // All other fields are not supported and thus must not be set @@ -1634,11 +1634,11 @@ func validatePersistentVolumeClaimTemplateObjectMeta(objMeta *metav1.ObjectMeta, // but then adding a new one to ObjectMeta wouldn't be checked // unless this code gets updated. Instead, we ensure that // only allowed fields are set via reflection. - allErrs = append(allErrs, validateFieldAllowList(*objMeta, allowedPVCTemplateObjectMetaFields, "cannot be set for an ephemeral volume", fldPath)...) + allErrs = append(allErrs, validateFieldAllowList(*objMeta, allowedTemplateObjectMetaFields, "cannot be set", fldPath)...) return allErrs } -var allowedPVCTemplateObjectMetaFields = map[string]bool{ +var allowedTemplateObjectMetaFields = map[string]bool{ "Annotations": true, "Labels": true, } @@ -2768,6 +2768,54 @@ func ValidateVolumeDevices(devices []core.VolumeDevice, volmounts map[string]str return allErrs } +func validatePodResourceClaims(claims []core.PodResourceClaim, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + podClaimNames := sets.NewString() + for i, claim := range claims { + allErrs = append(allErrs, validatePodResourceClaim(claim, &podClaimNames, fldPath.Index(i))...) + } + return allErrs +} + +// gatherPodResourceClaimNames returns a set of all non-empty +// PodResourceClaim.Name values. Validation that those names are valid is +// handled by validatePodResourceClaims. +func gatherPodResourceClaimNames(claims []core.PodResourceClaim) sets.String { + podClaimNames := sets.String{} + for _, claim := range claims { + if claim.Name != "" { + podClaimNames.Insert(claim.Name) + } + } + return podClaimNames +} + +func validatePodResourceClaim(claim core.PodResourceClaim, podClaimNames *sets.String, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + if claim.Name == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) + } else if podClaimNames.Has(claim.Name) { + allErrs = append(allErrs, field.Duplicate(fldPath.Child("name"), claim.Name)) + } else { + allErrs = append(allErrs, ValidateDNS1123Label(claim.Name, fldPath.Child("name"))...) + podClaimNames.Insert(claim.Name) + } + allErrs = append(allErrs, validatePodResourceClaimSource(claim.Source, fldPath.Child("source"))...) + + return allErrs +} + +func validatePodResourceClaimSource(claimSource core.ClaimSource, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + if claimSource.ResourceClaimName != nil && claimSource.ResourceClaimTemplateName != nil { + allErrs = append(allErrs, field.Invalid(fldPath, claimSource, "at most one of `resourceClaimName` or `resourceClaimTemplateName` may be specified")) + } + if claimSource.ResourceClaimName == nil && claimSource.ResourceClaimTemplateName == nil { + allErrs = append(allErrs, field.Invalid(fldPath, claimSource, "must specify one of: `resourceClaimName`, `resourceClaimTemplateName`")) + } + return allErrs +} + func validateProbe(probe *core.Probe, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} @@ -2990,8 +3038,8 @@ func validatePullPolicy(policy core.PullPolicy, fldPath *field.Path) field.Error // validateEphemeralContainers is called by pod spec and template validation to validate the list of ephemeral containers. // Note that this is called for pod template even though ephemeral containers aren't allowed in pod templates. -func validateEphemeralContainers(ephemeralContainers []core.EphemeralContainer, containers, initContainers []core.Container, volumes map[string]core.VolumeSource, fldPath *field.Path, opts PodValidationOptions) field.ErrorList { - allErrs := field.ErrorList{} +func validateEphemeralContainers(ephemeralContainers []core.EphemeralContainer, containers, initContainers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, fldPath *field.Path, opts PodValidationOptions) field.ErrorList { + var allErrs field.ErrorList if len(ephemeralContainers) == 0 { return allErrs @@ -3011,7 +3059,7 @@ func validateEphemeralContainers(ephemeralContainers []core.EphemeralContainer, idxPath := fldPath.Index(i) c := (*core.Container)(&ec.EphemeralContainerCommon) - allErrs = append(allErrs, validateContainerCommon(c, volumes, idxPath, opts)...) + allErrs = append(allErrs, validateContainerCommon(c, volumes, podClaimNames, idxPath, opts)...) // Ephemeral containers don't need looser constraints for pod templates, so it's convenient to apply both validations // here where we've already converted EphemeralContainerCommon to Container. allErrs = append(allErrs, validateContainerOnlyForPod(c, idxPath)...) @@ -3049,7 +3097,7 @@ func validateEphemeralContainers(ephemeralContainers []core.EphemeralContainer, return allErrs } -// validateFieldAcceptList checks that only allowed fields are set. +// ValidateFieldAcceptList checks that only allowed fields are set. // The value must be a struct (not a pointer to a struct!). func validateFieldAllowList(value interface{}, allowedFields map[string]bool, errorText string, fldPath *field.Path) field.ErrorList { var allErrs field.ErrorList @@ -3073,7 +3121,7 @@ func validateFieldAllowList(value interface{}, allowedFields map[string]bool, er } // validateInitContainers is called by pod spec and template validation to validate the list of init containers -func validateInitContainers(containers []core.Container, regularContainers []core.Container, volumes map[string]core.VolumeSource, fldPath *field.Path, opts PodValidationOptions) field.ErrorList { +func validateInitContainers(containers []core.Container, regularContainers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, fldPath *field.Path, opts PodValidationOptions) field.ErrorList { var allErrs field.ErrorList allNames := sets.String{} @@ -3084,7 +3132,7 @@ func validateInitContainers(containers []core.Container, regularContainers []cor idxPath := fldPath.Index(i) // Apply the validation common to all container types - allErrs = append(allErrs, validateContainerCommon(&ctr, volumes, idxPath, opts)...) + allErrs = append(allErrs, validateContainerCommon(&ctr, volumes, podClaimNames, idxPath, opts)...) // Names must be unique within regular and init containers. Collisions with ephemeral containers // will be detected by validateEphemeralContainers(). @@ -3117,8 +3165,8 @@ func validateInitContainers(containers []core.Container, regularContainers []cor // validateContainerCommon applies validation common to all container types. It's called by regular, init, and ephemeral // container list validation to require a properly formatted name, image, etc. -func validateContainerCommon(ctr *core.Container, volumes map[string]core.VolumeSource, path *field.Path, opts PodValidationOptions) field.ErrorList { - allErrs := field.ErrorList{} +func validateContainerCommon(ctr *core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, path *field.Path, opts PodValidationOptions) field.ErrorList { + var allErrs field.ErrorList namePath := path.Child("name") if len(ctr.Name) == 0 { @@ -3154,7 +3202,7 @@ func validateContainerCommon(ctr *core.Container, volumes map[string]core.Volume allErrs = append(allErrs, ValidateVolumeMounts(ctr.VolumeMounts, volDevices, volumes, ctr, path.Child("volumeMounts"))...) allErrs = append(allErrs, ValidateVolumeDevices(ctr.VolumeDevices, volMounts, volumes, path.Child("volumeDevices"))...) allErrs = append(allErrs, validatePullPolicy(ctr.ImagePullPolicy, path.Child("imagePullPolicy"))...) - allErrs = append(allErrs, ValidateResourceRequirements(&ctr.Resources, path.Child("resources"), opts)...) + allErrs = append(allErrs, ValidateResourceRequirements(&ctr.Resources, podClaimNames, path.Child("resources"), opts)...) allErrs = append(allErrs, ValidateSecurityContext(ctr.SecurityContext, path.Child("securityContext"))...) return allErrs } @@ -3207,7 +3255,7 @@ func validateHostUsers(spec *core.PodSpec, fldPath *field.Path) field.ErrorList } // validateContainers is called by pod spec and template validation to validate the list of regular containers. -func validateContainers(containers []core.Container, volumes map[string]core.VolumeSource, fldPath *field.Path, opts PodValidationOptions) field.ErrorList { +func validateContainers(containers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, fldPath *field.Path, opts PodValidationOptions) field.ErrorList { allErrs := field.ErrorList{} if len(containers) == 0 { @@ -3219,7 +3267,7 @@ func validateContainers(containers []core.Container, volumes map[string]core.Vol path := fldPath.Index(i) // Apply validation common to all containers - allErrs = append(allErrs, validateContainerCommon(&ctr, volumes, path, opts)...) + allErrs = append(allErrs, validateContainerCommon(&ctr, volumes, podClaimNames, path, opts)...) // Container names must be unique within the list of regular containers. // Collisions with init or ephemeral container names will be detected by the init or ephemeral @@ -3697,9 +3745,11 @@ func ValidatePodSpec(spec *core.PodSpec, podMeta *metav1.ObjectMeta, fldPath *fi vols, vErrs := ValidateVolumes(spec.Volumes, podMeta, fldPath.Child("volumes"), opts) allErrs = append(allErrs, vErrs...) - allErrs = append(allErrs, validateContainers(spec.Containers, vols, fldPath.Child("containers"), opts)...) - allErrs = append(allErrs, validateInitContainers(spec.InitContainers, spec.Containers, vols, fldPath.Child("initContainers"), opts)...) - allErrs = append(allErrs, validateEphemeralContainers(spec.EphemeralContainers, spec.Containers, spec.InitContainers, vols, fldPath.Child("ephemeralContainers"), opts)...) + podClaimNames := gatherPodResourceClaimNames(spec.ResourceClaims) + allErrs = append(allErrs, validatePodResourceClaims(spec.ResourceClaims, fldPath.Child("resourceClaims"))...) + allErrs = append(allErrs, validateContainers(spec.Containers, vols, podClaimNames, fldPath.Child("containers"), opts)...) + allErrs = append(allErrs, validateInitContainers(spec.InitContainers, spec.Containers, vols, podClaimNames, fldPath.Child("initContainers"), opts)...) + allErrs = append(allErrs, validateEphemeralContainers(spec.EphemeralContainers, spec.Containers, spec.InitContainers, vols, podClaimNames, fldPath.Child("ephemeralContainers"), opts)...) allErrs = append(allErrs, validateRestartPolicy(&spec.RestartPolicy, fldPath.Child("restartPolicy"))...) allErrs = append(allErrs, validateDNSPolicy(&spec.DNSPolicy, fldPath.Child("dnsPolicy"))...) allErrs = append(allErrs, unversionedvalidation.ValidateLabels(spec.NodeSelector, fldPath.Child("nodeSelector"))...) @@ -5856,7 +5906,7 @@ func validateBasicResource(quantity resource.Quantity, fldPath *field.Path) fiel } // Validates resource requirement spec. -func ValidateResourceRequirements(requirements *core.ResourceRequirements, fldPath *field.Path, opts PodValidationOptions) field.ErrorList { +func ValidateResourceRequirements(requirements *core.ResourceRequirements, podClaimNames sets.String, fldPath *field.Path, opts PodValidationOptions) field.ErrorList { allErrs := field.ErrorList{} limPath := fldPath.Child("limits") reqPath := fldPath.Child("requests") @@ -5919,6 +5969,42 @@ func ValidateResourceRequirements(requirements *core.ResourceRequirements, fldPa allErrs = append(allErrs, field.Forbidden(fldPath, "HugePages require cpu or memory")) } + allErrs = append(allErrs, validateResourceClaimNames(requirements.Claims, podClaimNames, fldPath.Child("claims"))...) + + return allErrs +} + +// validateResourceClaimNames checks that the names in +// ResourceRequirements.Claims have a corresponding entry in +// PodSpec.ResourceClaims. +func validateResourceClaimNames(claims []core.ResourceClaim, podClaimNames sets.String, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + names := sets.String{} + for i, claim := range claims { + name := claim.Name + if name == "" { + allErrs = append(allErrs, field.Required(fldPath.Index(i), "")) + } else { + if names.Has(name) { + allErrs = append(allErrs, field.Duplicate(fldPath.Index(i), name)) + } else { + names.Insert(name) + } + if !podClaimNames.Has(name) { + // field.NotFound doesn't accept an + // explanation. Adding one here is more + // user-friendly. + error := field.NotFound(fldPath.Index(i), name) + error.Detail = "must be one of the names in pod.spec.resourceClaims" + if len(podClaimNames) == 0 { + error.Detail += " which is empty" + } else { + error.Detail += ": " + strings.Join(podClaimNames.List(), ", ") + } + allErrs = append(allErrs, error) + } + } + } return allErrs } diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index 0e64d0b301d..bf669a7fbf3 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -5385,7 +5385,7 @@ func TestAlphaLocalStorageCapacityIsolation(t *testing.T) { resource.BinarySI), }, } - if errs := ValidateResourceRequirements(&containerLimitCase, field.NewPath("resources"), PodValidationOptions{}); len(errs) != 0 { + if errs := ValidateResourceRequirements(&containerLimitCase, nil, field.NewPath("resources"), PodValidationOptions{}); len(errs) != 0 { t.Errorf("expected success: %v", errs) } } @@ -6855,7 +6855,7 @@ func TestValidateEphemeralContainers(t *testing.T) { }, }, } { - if errs := validateEphemeralContainers(ephemeralContainers, containers, initContainers, vols, field.NewPath("ephemeralContainers"), PodValidationOptions{}); len(errs) != 0 { + if errs := validateEphemeralContainers(ephemeralContainers, containers, initContainers, vols, nil, field.NewPath("ephemeralContainers"), PodValidationOptions{}); len(errs) != 0 { t.Errorf("expected success for '%s' but got errors: %v", title, errs) } } @@ -7137,7 +7137,7 @@ func TestValidateEphemeralContainers(t *testing.T) { for _, tc := range tcs { t.Run(tc.title+"__@L"+tc.line, func(t *testing.T) { - errs := validateEphemeralContainers(tc.ephemeralContainers, containers, initContainers, vols, field.NewPath("ephemeralContainers"), PodValidationOptions{}) + errs := validateEphemeralContainers(tc.ephemeralContainers, containers, initContainers, vols, nil, field.NewPath("ephemeralContainers"), PodValidationOptions{}) if len(errs) == 0 { t.Fatal("expected error but received none") } @@ -7416,7 +7416,7 @@ func TestValidateContainers(t *testing.T) { TerminationMessagePolicy: "File", }, } - if errs := validateContainers(successCase, volumeDevices, field.NewPath("field"), PodValidationOptions{}); len(errs) != 0 { + if errs := validateContainers(successCase, volumeDevices, nil, field.NewPath("field"), PodValidationOptions{}); len(errs) != 0 { t.Errorf("expected success: %v", errs) } @@ -8040,7 +8040,7 @@ func TestValidateContainers(t *testing.T) { } for _, tc := range errorCases { t.Run(tc.title+"__@L"+tc.line, func(t *testing.T) { - errs := validateContainers(tc.containers, volumeDevices, field.NewPath("containers"), PodValidationOptions{}) + errs := validateContainers(tc.containers, volumeDevices, nil, field.NewPath("containers"), PodValidationOptions{}) if len(errs) == 0 { t.Fatal("expected error but received none") } @@ -8090,7 +8090,7 @@ func TestValidateInitContainers(t *testing.T) { TerminationMessagePolicy: "File", }, } - if errs := validateInitContainers(successCase, containers, volumeDevices, field.NewPath("field"), PodValidationOptions{}); len(errs) != 0 { + if errs := validateInitContainers(successCase, containers, volumeDevices, nil, field.NewPath("field"), PodValidationOptions{}); len(errs) != 0 { t.Errorf("expected success: %v", errs) } @@ -8282,7 +8282,7 @@ func TestValidateInitContainers(t *testing.T) { } for _, tc := range errorCases { t.Run(tc.title+"__@L"+tc.line, func(t *testing.T) { - errs := validateInitContainers(tc.initContainers, containers, volumeDevices, field.NewPath("initContainers"), PodValidationOptions{}) + errs := validateInitContainers(tc.initContainers, containers, volumeDevices, nil, field.NewPath("initContainers"), PodValidationOptions{}) if len(errs) == 0 { t.Fatal("expected error but received none") } @@ -18625,6 +18625,9 @@ func TestValidateOSFields(t *testing.T) { "Priority", "PriorityClassName", "ReadinessGates", + "ResourceClaims[*].Name", + "ResourceClaims[*].Source.ResourceClaimName", + "ResourceClaims[*].Source.ResourceClaimTemplateName", "RestartPolicy", "RuntimeClassName", "SchedulerName", @@ -20928,7 +20931,7 @@ func TestValidateResourceRequirements(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - if errs := ValidateResourceRequirements(&tc.requirements, path, tc.opts); len(errs) != 0 { + if errs := ValidateResourceRequirements(&tc.requirements, nil, path, tc.opts); len(errs) != 0 { t.Errorf("unexpected errors: %v", errs) } }) @@ -20955,7 +20958,7 @@ func TestValidateResourceRequirements(t *testing.T) { for _, tc := range errTests { t.Run(tc.name, func(t *testing.T) { - if errs := ValidateResourceRequirements(&tc.requirements, path, tc.opts); len(errs) == 0 { + if errs := ValidateResourceRequirements(&tc.requirements, nil, path, tc.opts); len(errs) == 0 { t.Error("expected errors") } }) @@ -21695,3 +21698,220 @@ func TestValidatePVSecretReference(t *testing.T) { }) } } + +func TestValidateDynamicResourceAllocation(t *testing.T) { + externalClaimName := "some-claim" + externalClaimTemplateName := "some-claim-template" + goodClaimSource := core.ClaimSource{ + ResourceClaimName: &externalClaimName, + } + + successCases := map[string]core.PodSpec{ + "resource claim reference": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "my-claim"}}}}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my-claim", + Source: core.ClaimSource{ + ResourceClaimName: &externalClaimName, + }, + }, + }, + }, + "resource claim template": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "my-claim"}}}}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my-claim", + Source: core.ClaimSource{ + ResourceClaimTemplateName: &externalClaimTemplateName, + }, + }, + }, + }, + "multiple claims": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "my-claim"}, {Name: "another-claim"}}}}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my-claim", + Source: goodClaimSource, + }, + { + Name: "another-claim", + Source: goodClaimSource, + }, + }, + }, + "init container": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "my-claim"}}}}}, + InitContainers: []core.Container{{Name: "ctr-init", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "my-claim"}}}}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my-claim", + Source: goodClaimSource, + }, + }, + }, + } + for k, v := range successCases { + t.Run(k, func(t *testing.T) { + if errs := ValidatePodSpec(&v, nil, field.NewPath("field"), PodValidationOptions{}); len(errs) != 0 { + t.Errorf("expected success: %v", errs) + } + }) + } + + failureCases := map[string]core.PodSpec{ + "pod claim name with prefix": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "../my-claim", + Source: goodClaimSource, + }, + }, + }, + "pod claim name with path": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my/claim", + Source: goodClaimSource, + }, + }, + }, + "pod claim name empty": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "", + Source: goodClaimSource, + }, + }, + }, + "duplicate pod claim entries": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my-claim", + Source: goodClaimSource, + }, + { + Name: "my-claim", + Source: goodClaimSource, + }, + }, + }, + "resource claim source empty": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "my-claim"}}}}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my-claim", + Source: core.ClaimSource{}, + }, + }, + }, + "resource claim reference and template": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "my-claim"}}}}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my-claim", + Source: core.ClaimSource{ + ResourceClaimName: &externalClaimName, + ResourceClaimTemplateName: &externalClaimTemplateName, + }, + }, + }, + }, + "claim not found": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "no-such-claim"}}}}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my-claim", + Source: goodClaimSource, + }, + }, + }, + "claim name empty": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: ""}}}}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my-claim", + Source: goodClaimSource, + }, + }, + }, + "pod claim name duplicates": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "my-claim"}, {Name: "my-claim"}}}}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my-claim", + Source: goodClaimSource, + }, + }, + }, + "no claims defined": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "my-claim"}}}}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + }, + "duplicate pod claim name": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "my-claim"}}}}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my-claim", + Source: goodClaimSource, + }, + { + Name: "my-claim", + Source: goodClaimSource, + }, + }, + }, + "ephemeral container don't support resource requirements": { + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "my-claim"}}}}}, + EphemeralContainers: []core.EphemeralContainer{{EphemeralContainerCommon: core.EphemeralContainerCommon{Name: "ctr-ephemeral", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File", Resources: core.ResourceRequirements{Claims: []core.ResourceClaim{{Name: "my-claim"}}}}, TargetContainerName: "ctr"}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + ResourceClaims: []core.PodResourceClaim{ + { + Name: "my-claim", + Source: goodClaimSource, + }, + }, + }, + } + for k, v := range failureCases { + if errs := ValidatePodSpec(&v, nil, field.NewPath("field"), PodValidationOptions{}); len(errs) == 0 { + t.Errorf("expected failure for %q", k) + } + } +} diff --git a/pkg/apis/core/zz_generated.deepcopy.go b/pkg/apis/core/zz_generated.deepcopy.go index a7a4521d130..857843371a3 100644 --- a/pkg/apis/core/zz_generated.deepcopy.go +++ b/pkg/apis/core/zz_generated.deepcopy.go @@ -419,6 +419,32 @@ func (in *CinderVolumeSource) DeepCopy() *CinderVolumeSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClaimSource) DeepCopyInto(out *ClaimSource) { + *out = *in + if in.ResourceClaimName != nil { + in, out := &in.ResourceClaimName, &out.ResourceClaimName + *out = new(string) + **out = **in + } + if in.ResourceClaimTemplateName != nil { + in, out := &in.ResourceClaimTemplateName, &out.ResourceClaimTemplateName + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimSource. +func (in *ClaimSource) DeepCopy() *ClaimSource { + if in == nil { + return nil + } + out := new(ClaimSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClientIPConfig) DeepCopyInto(out *ClientIPConfig) { *out = *in @@ -3728,6 +3754,23 @@ func (in *PodReadinessGate) DeepCopy() *PodReadinessGate { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodResourceClaim) DeepCopyInto(out *PodResourceClaim) { + *out = *in + in.Source.DeepCopyInto(&out.Source) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodResourceClaim. +func (in *PodResourceClaim) DeepCopy() *PodResourceClaim { + if in == nil { + return nil + } + out := new(PodResourceClaim) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PodSchedulingGate) DeepCopyInto(out *PodSchedulingGate) { *out = *in @@ -3982,6 +4025,13 @@ func (in *PodSpec) DeepCopyInto(out *PodSpec) { *out = make([]PodSchedulingGate, len(*in)) copy(*out, *in) } + if in.ResourceClaims != nil { + in, out := &in.ResourceClaims, &out.ResourceClaims + *out = make([]PodResourceClaim, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -4560,6 +4610,22 @@ func (in *ReplicationControllerStatus) DeepCopy() *ReplicationControllerStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaim) DeepCopyInto(out *ResourceClaim) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaim. +func (in *ResourceClaim) DeepCopy() *ResourceClaim { + if in == nil { + return nil + } + out := new(ResourceClaim) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceFieldSelector) DeepCopyInto(out *ResourceFieldSelector) { *out = *in @@ -4740,6 +4806,11 @@ func (in *ResourceRequirements) DeepCopyInto(out *ResourceRequirements) { (*out)[key] = val.DeepCopy() } } + if in.Claims != nil { + in, out := &in.Claims, &out.Claims + *out = make([]ResourceClaim, len(*in)) + copy(*out, *in) + } return } diff --git a/pkg/apis/node/validation/validation.go b/pkg/apis/node/validation/validation.go index 60f6161611f..4e0a20aaf1e 100644 --- a/pkg/apis/node/validation/validation.go +++ b/pkg/apis/node/validation/validation.go @@ -54,7 +54,7 @@ func ValidateRuntimeClassUpdate(new, old *node.RuntimeClass) field.ErrorList { func validateOverhead(overhead *node.Overhead, fldPath *field.Path) field.ErrorList { // reuse the ResourceRequirements validation logic - return corevalidation.ValidateResourceRequirements(&core.ResourceRequirements{Limits: overhead.PodFixed}, fldPath, + return corevalidation.ValidateResourceRequirements(&core.ResourceRequirements{Limits: overhead.PodFixed}, nil, fldPath, corevalidation.PodValidationOptions{}) } diff --git a/pkg/apis/resource/OWNERS b/pkg/apis/resource/OWNERS new file mode 100644 index 00000000000..98397072ae5 --- /dev/null +++ b/pkg/apis/resource/OWNERS @@ -0,0 +1,6 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +reviewers: + - bart0sh + - klueska + - pohly diff --git a/pkg/apis/resource/doc.go b/pkg/apis/resource/doc.go new file mode 100644 index 00000000000..f798bef1f94 --- /dev/null +++ b/pkg/apis/resource/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package + +// Package resource contains the latest (or "internal") version of the +// Kubernetes resource API objects. +package resource // import "k8s.io/kubernetes/pkg/apis/resource" diff --git a/pkg/apis/resource/fuzzer/fuzzer.go b/pkg/apis/resource/fuzzer/fuzzer.go new file mode 100644 index 00000000000..5cf5b5e635b --- /dev/null +++ b/pkg/apis/resource/fuzzer/fuzzer.go @@ -0,0 +1,40 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fuzzer + +import ( + fuzz "github.com/google/gofuzz" + + runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/kubernetes/pkg/apis/resource" +) + +// Funcs contains the fuzzer functions for the resource group. +var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { + return []interface{}{ + func(obj *resource.ResourceClaimSpec, c fuzz.Continue) { + c.FuzzNoCustom(obj) // fuzz self without calling this function again + + // Custom fuzzing for allocation mode: pick one valid mode randomly. + modes := []resource.AllocationMode{ + resource.AllocationModeImmediate, + resource.AllocationModeWaitForFirstConsumer, + } + obj.AllocationMode = modes[c.Rand.Intn(len(modes))] + }, + } +} diff --git a/pkg/apis/resource/install/install.go b/pkg/apis/resource/install/install.go new file mode 100644 index 00000000000..f0495e7468a --- /dev/null +++ b/pkg/apis/resource/install/install.go @@ -0,0 +1,38 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package install installs the resource API, making it available as an +// option to all of the API encoding/decoding machinery. +package install + +import ( + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/kubernetes/pkg/apis/resource/v1alpha1" +) + +func init() { + Install(legacyscheme.Scheme) +} + +// Install registers the API group and adds types to a scheme +func Install(scheme *runtime.Scheme) { + utilruntime.Must(resource.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion)) +} diff --git a/pkg/apis/resource/install/install_test.go b/pkg/apis/resource/install/install_test.go new file mode 100644 index 00000000000..ed034a71d77 --- /dev/null +++ b/pkg/apis/resource/install/install_test.go @@ -0,0 +1,75 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package install + +import ( + "encoding/json" + "reflect" + "testing" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kubernetes/pkg/api/legacyscheme" + internal "k8s.io/kubernetes/pkg/apis/resource" +) + +func TestResourceVersioner(t *testing.T) { + claim := internal.ResourceClaim{ObjectMeta: metav1.ObjectMeta{ResourceVersion: "10"}} + version, err := meta.NewAccessor().ResourceVersion(&claim) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if version != "10" { + t.Errorf("unexpected version %v", version) + } + + claimList := internal.ResourceClaimList{ListMeta: metav1.ListMeta{ResourceVersion: "10"}} + version, err = meta.NewAccessor().ResourceVersion(&claimList) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if version != "10" { + t.Errorf("unexpected version %v", version) + } +} + +func TestCodec(t *testing.T) { + claim := internal.ResourceClaim{} + data, err := runtime.Encode(legacyscheme.Codecs.LegacyCodec(schema.GroupVersion{Group: "resource.k8s.io", Version: "v1alpha1"}), &claim) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + other := internal.ResourceClaim{} + if err := json.Unmarshal(data, &other); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if other.APIVersion != "resource.k8s.io/v1alpha1" || other.Kind != "ResourceClaim" { + t.Errorf("unexpected unmarshalled object %#v", other) + } +} + +func TestUnversioned(t *testing.T) { + for _, obj := range []runtime.Object{ + &metav1.Status{}, + } { + if unversioned, ok := legacyscheme.Scheme.IsUnversioned(obj); !unversioned || !ok { + t.Errorf("%v is expected to be unversioned", reflect.TypeOf(obj)) + } + } +} diff --git a/pkg/apis/resource/register.go b/pkg/apis/resource/register.go new file mode 100644 index 00000000000..35b89de0fb1 --- /dev/null +++ b/pkg/apis/resource/register.go @@ -0,0 +1,66 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "resource.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal} + +// Kind takes an unqualified kind and returns a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // SchemeBuilder object to register various known types + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + + // AddToScheme represents a func that can be used to apply all the registered + // funcs in a scheme + AddToScheme = SchemeBuilder.AddToScheme +) + +func addKnownTypes(scheme *runtime.Scheme) error { + if err := scheme.AddIgnoredConversionType(&metav1.TypeMeta{}, &metav1.TypeMeta{}); err != nil { + return err + } + scheme.AddKnownTypes(SchemeGroupVersion, + &ResourceClass{}, + &ResourceClassList{}, + &ResourceClaim{}, + &ResourceClaimList{}, + &ResourceClaimTemplate{}, + &ResourceClaimTemplateList{}, + &PodScheduling{}, + &PodSchedulingList{}, + ) + + return nil +} diff --git a/pkg/apis/resource/types.go b/pkg/apis/resource/types.go new file mode 100644 index 00000000000..627a09cb425 --- /dev/null +++ b/pkg/apis/resource/types.go @@ -0,0 +1,404 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/apis/core" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ResourceClaim describes which resources are needed by a resource consumer. +// Its status tracks whether the resource has been allocated and what the +// resulting attributes are. +// +// This is an alpha type and requires enabling the DynamicResourceAllocation +// feature gate. +type ResourceClaim struct { + metav1.TypeMeta + // Standard object metadata + // +optional + metav1.ObjectMeta + + // Spec describes the desired attributes of a resource that then needs + // to be allocated. It can only be set once when creating the + // ResourceClaim. + Spec ResourceClaimSpec + + // Status describes whether the resource is available and with which + // attributes. + // +optional + Status ResourceClaimStatus +} + +// ResourceClaimSpec defines how a resource is to be allocated. +type ResourceClaimSpec struct { + // ResourceClassName references the driver and additional parameters + // via the name of a ResourceClass that was created as part of the + // driver deployment. + ResourceClassName string + + // ParametersRef references a separate object with arbitrary parameters + // that will be used by the driver when allocating a resource for the + // claim. + // + // The object must be in the same namespace as the ResourceClaim. + // +optional + ParametersRef *ResourceClaimParametersReference + + // Allocation can start immediately or when a Pod wants to use the + // resource. "WaitForFirstConsumer" is the default. + // +optional + AllocationMode AllocationMode +} + +// AllocationMode describes whether a ResourceClaim gets allocated immediately +// when it gets created (AllocationModeImmediate) or whether allocation is +// delayed until it is needed for a Pod +// (AllocationModeWaitForFirstConsumer). Other modes might get added in the +// future. +type AllocationMode string + +const ( + // When a ResourceClaim has AllocationModeWaitForFirstConsumer, allocation is + // delayed until a Pod gets scheduled that needs the ResourceClaim. The + // scheduler will consider all resource requirements of that Pod and + // trigger allocation for a node that fits the Pod. + AllocationModeWaitForFirstConsumer AllocationMode = "WaitForFirstConsumer" + + // When a ResourceClaim has AllocationModeImmediate, allocation starts + // as soon as the ResourceClaim gets created. This is done without + // considering the needs of Pods that will use the ResourceClaim + // because those Pods are not known yet. + AllocationModeImmediate AllocationMode = "Immediate" +) + +// ResourceClaimStatus tracks whether the resource has been allocated and what +// the resulting attributes are. +type ResourceClaimStatus struct { + // DriverName is a copy of the driver name from the ResourceClass at + // the time when allocation started. + // +optional + DriverName string + + // Allocation is set by the resource driver once a resource has been + // allocated successfully. If this is not specified, the resource is + // not yet allocated. + // +optional + Allocation *AllocationResult + + // ReservedFor indicates which entities are currently allowed to use + // the claim. A Pod which references a ResourceClaim which is not + // reserved for that Pod will not be started. + // + // There can be at most 32 such reservations. This may get increased in + // the future, but not reduced. + // +optional + ReservedFor []ResourceClaimConsumerReference + + // DeallocationRequested indicates that a ResourceClaim is to be + // deallocated. + // + // The driver then must deallocate this claim and reset the field + // together with clearing the Allocation field. + // + // While DeallocationRequested is set, no new consumers may be added to + // ReservedFor. + // +optional + DeallocationRequested bool +} + +// ReservedForMaxSize is the maximum number of entries in +// claim.status.reservedFor. +const ResourceClaimReservedForMaxSize = 32 + +// AllocationResult contains attributed of an allocated resource. +type AllocationResult struct { + // ResourceHandle contains arbitrary data returned by the driver after a + // successful allocation. This is opaque for + // Kubernetes. Driver documentation may explain to users how to + // interpret this data if needed. + // + // The maximum size of this field is 16KiB. This may get + // increased in the future, but not reduced. + // +optional + ResourceHandle string + + // This field will get set by the resource driver after it has + // allocated the resource driver to inform the scheduler where it can + // schedule Pods using the ResourceClaim. + // + // Setting this field is optional. If null, the resource is available + // everywhere. + // +optional + AvailableOnNodes *core.NodeSelector + + // Shareable determines whether the resource supports more + // than one consumer at a time. + // +optional + Shareable bool +} + +// ResourceHandleMaxSize is the maximum size of allocation.resourceHandle. +const ResourceHandleMaxSize = 16 * 1024 + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ResourceClaimList is a collection of claims. +type ResourceClaimList struct { + metav1.TypeMeta + // Standard list metadata + // +optional + metav1.ListMeta + + // Items is the list of resource claims. + Items []ResourceClaim +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PodScheduling objects hold information that is needed to schedule +// a Pod with ResourceClaims that use "WaitForFirstConsumer" allocation +// mode. +// +// This is an alpha type and requires enabling the DynamicResourceAllocation +// feature gate. +type PodScheduling struct { + metav1.TypeMeta + // Standard object metadata + // +optional + metav1.ObjectMeta + + // Spec describes where resources for the Pod are needed. + Spec PodSchedulingSpec + + // Status describes where resources for the Pod can be allocated. + Status PodSchedulingStatus +} + +// PodSchedulingSpec describes where resources for the Pod are needed. +type PodSchedulingSpec struct { + // SelectedNode is the node for which allocation of ResourceClaims that + // are referenced by the Pod and that use "WaitForFirstConsumer" + // allocation is to be attempted. + SelectedNode string + + // PotentialNodes lists nodes where the Pod might be able to run. + // + // The size of this field is limited to 128. This is large enough for + // many clusters. Larger clusters may need more attempts to find a node + // that suits all pending resources. This may get increased in the + // future, but not reduced. + // +optional + PotentialNodes []string +} + +// PodSchedulingStatus describes where resources for the Pod can be allocated. +type PodSchedulingStatus struct { + // ResourceClaims describes resource availability for each + // pod.spec.resourceClaim entry where the corresponding ResourceClaim + // uses "WaitForFirstConsumer" allocation mode. + // +optional + ResourceClaims []ResourceClaimSchedulingStatus + + // If there ever is a need to support other kinds of resources + // than ResourceClaim, then new fields could get added here + // for those other resources. +} + +// ResourceClaimSchedulingStatus contains information about one particular +// ResourceClaim with "WaitForFirstConsumer" allocation mode. +type ResourceClaimSchedulingStatus struct { + // Name matches the pod.spec.resourceClaims[*].Name field. + Name string + + // UnsuitableNodes lists nodes that the ResourceClaim cannot be + // allocated for. + // + // The size of this field is limited to 128, the same as for + // PodSchedulingSpec.PotentialNodes. This may get increased in the + // future, but not reduced. + // +optional + UnsuitableNodes []string +} + +// PodSchedulingNodeListMaxSize defines the maximum number of entries in the +// node lists that are stored in PodScheduling objects. This limit is part +// of the API. +const PodSchedulingNodeListMaxSize = 128 + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PodSchedulingList is a collection of Pod scheduling objects. +type PodSchedulingList struct { + metav1.TypeMeta + // Standard list metadata + // +optional + metav1.ListMeta + + // Items is the list of PodScheduling objects. + Items []PodScheduling +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ResourceClass is used by administrators to influence how resources +// are allocated. +// +// This is an alpha type and requires enabling the DynamicResourceAllocation +// feature gate. +type ResourceClass struct { + metav1.TypeMeta + // Standard object metadata + // +optional + metav1.ObjectMeta + + // DriverName defines the name of the dynamic resource driver that is + // used for allocation of a ResourceClaim that uses this class. + // + // Resource drivers have a unique name in forward domain order + // (acme.example.com). + DriverName string + + // ParametersRef references an arbitrary separate object that may hold + // parameters that will be used by the driver when allocating a + // resource that uses this class. A dynamic resource driver can + // distinguish between parameters stored here and and those stored in + // ResourceClaimSpec. + // +optional + ParametersRef *ResourceClassParametersReference + + // Only nodes matching the selector will be considered by the scheduler + // when trying to find a Node that fits a Pod when that Pod uses + // a ResourceClaim that has not been allocated yet. + // + // Setting this field is optional. If null, all nodes are candidates. + // +optional + SuitableNodes *core.NodeSelector +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ResourceClassList is a collection of classes. +type ResourceClassList struct { + metav1.TypeMeta + // Standard list metadata + // +optional + metav1.ListMeta + + // Items is the list of resource classes. + Items []ResourceClass +} + +// ResourceClassParametersReference contains enough information to let you +// locate the parameters for a ResourceClass. +type ResourceClassParametersReference struct { + // APIGroup is the group for the resource being referenced. It is + // empty for the core API. This matches the group in the APIVersion + // that is used when creating the resources. + // +optional + APIGroup string + // Kind is the type of resource being referenced. This is the same + // value as in the parameter object's metadata. + Kind string + // Name is the name of resource being referenced. + Name string + // Namespace that contains the referenced resource. Must be empty + // for cluster-scoped resources and non-empty for namespaced + // resources. + // +optional + Namespace string +} + +// ResourceClaimParametersReference contains enough information to let you +// locate the parameters for a ResourceClaim. The object must be in the same +// namespace as the ResourceClaim. +type ResourceClaimParametersReference struct { + // APIGroup is the group for the resource being referenced. It is + // empty for the core API. This matches the group in the APIVersion + // that is used when creating the resources. + // +optional + APIGroup string + // Kind is the type of resource being referenced. This is the same + // value as in the parameter object's metadata, for example "ConfigMap". + Kind string + // Name is the name of resource being referenced. + Name string +} + +// ResourceClaimConsumerReference contains enough information to let you +// locate the consumer of a ResourceClaim. The user must be a resource in the same +// namespace as the ResourceClaim. +type ResourceClaimConsumerReference struct { + // APIGroup is the group for the resource being referenced. It is + // empty for the core API. This matches the group in the APIVersion + // that is used when creating the resources. + // +optional + APIGroup string + // Resource is the type of resource being referenced, for example "pods". + Resource string + // Name is the name of resource being referenced. + Name string + // UID identifies exactly one incarnation of the resource. + UID types.UID +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ResourceClaimTemplate is used to produce ResourceClaim objects. +type ResourceClaimTemplate struct { + metav1.TypeMeta + // Standard object metadata + // +optional + metav1.ObjectMeta + + // Describes the ResourceClaim that is to be generated. + // + // This field is immutable. A ResourceClaim will get created by the + // control plane for a Pod when needed and then not get updated + // anymore. + Spec ResourceClaimTemplateSpec +} + +// ResourceClaimTemplateSpec contains the metadata and fields for a ResourceClaim. +type ResourceClaimTemplateSpec struct { + // ObjectMeta may contain labels and annotations that will be copied into the PVC + // when creating it. No other fields are allowed and will be rejected during + // validation. + // +optional + metav1.ObjectMeta + + // Spec for the ResourceClaim. The entire content is copied unchanged + // into the ResourceClaim that gets created from this template. The + // same fields as in a ResourceClaim are also valid here. + Spec ResourceClaimSpec +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ResourceClaimTemplateList is a collection of claim templates. +type ResourceClaimTemplateList struct { + metav1.TypeMeta + // Standard list metadata + // +optional + metav1.ListMeta + + // Items is the list of resource claim templates. + Items []ResourceClaimTemplate +} diff --git a/pkg/apis/resource/v1alpha1/conversion.go b/pkg/apis/resource/v1alpha1/conversion.go new file mode 100644 index 00000000000..25db58993fd --- /dev/null +++ b/pkg/apis/resource/v1alpha1/conversion.go @@ -0,0 +1,25 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime" +) + +func addConversionFuncs(scheme *runtime.Scheme) error { + return nil +} diff --git a/pkg/apis/resource/v1alpha1/defaults.go b/pkg/apis/resource/v1alpha1/defaults.go new file mode 100644 index 00000000000..8bc728f389c --- /dev/null +++ b/pkg/apis/resource/v1alpha1/defaults.go @@ -0,0 +1,32 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "k8s.io/api/resource/v1alpha1" + "k8s.io/apimachinery/pkg/runtime" +) + +func addDefaultingFuncs(scheme *runtime.Scheme) error { + return RegisterDefaults(scheme) +} + +func SetDefaults_ResourceClaimSpec(obj *v1alpha1.ResourceClaimSpec) { + if obj.AllocationMode == "" { + obj.AllocationMode = v1alpha1.AllocationModeWaitForFirstConsumer + } +} diff --git a/pkg/apis/resource/v1alpha1/defaults_test.go b/pkg/apis/resource/v1alpha1/defaults_test.go new file mode 100644 index 00000000000..01dafd4fda4 --- /dev/null +++ b/pkg/apis/resource/v1alpha1/defaults_test.go @@ -0,0 +1,75 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1_test + +import ( + "reflect" + "testing" + + v1alpha1 "k8s.io/api/resource/v1alpha1" + "k8s.io/apimachinery/pkg/runtime" + + // ensure types are installed + "k8s.io/kubernetes/pkg/api/legacyscheme" + _ "k8s.io/kubernetes/pkg/apis/resource/install" +) + +func TestSetDefaultAllocationMode(t *testing.T) { + claim := &v1alpha1.ResourceClaim{} + + // field should be defaulted + defaultMode := v1alpha1.AllocationModeWaitForFirstConsumer + output := roundTrip(t, runtime.Object(claim)).(*v1alpha1.ResourceClaim) + outMode := output.Spec.AllocationMode + if outMode != defaultMode { + t.Errorf("Expected AllocationMode to be defaulted to: %+v, got: %+v", defaultMode, outMode) + } + + // field should not change + nonDefaultMode := v1alpha1.AllocationModeImmediate + claim = &v1alpha1.ResourceClaim{ + Spec: v1alpha1.ResourceClaimSpec{ + AllocationMode: nonDefaultMode, + }, + } + output = roundTrip(t, runtime.Object(claim)).(*v1alpha1.ResourceClaim) + outMode = output.Spec.AllocationMode + if outMode != v1alpha1.AllocationModeImmediate { + t.Errorf("Expected AllocationMode to remain %+v, got: %+v", nonDefaultMode, outMode) + } +} + +func roundTrip(t *testing.T, obj runtime.Object) runtime.Object { + codec := legacyscheme.Codecs.LegacyCodec(v1alpha1.SchemeGroupVersion) + data, err := runtime.Encode(codec, obj) + if err != nil { + t.Errorf("%v\n %#v", err, obj) + return nil + } + obj2, err := runtime.Decode(codec, data) + if err != nil { + t.Errorf("%v\nData: %s\nSource: %#v", err, string(data), obj) + return nil + } + obj3 := reflect.New(reflect.TypeOf(obj).Elem()).Interface().(runtime.Object) + err = legacyscheme.Scheme.Convert(obj2, obj3, nil) + if err != nil { + t.Errorf("%v\nSource: %#v", err, obj2) + return nil + } + return obj3 +} diff --git a/pkg/apis/resource/v1alpha1/doc.go b/pkg/apis/resource/v1alpha1/doc.go new file mode 100644 index 00000000000..77afe07224b --- /dev/null +++ b/pkg/apis/resource/v1alpha1/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/resource +// +k8s:conversion-gen-external-types=k8s.io/api/resource/v1alpha1 +// +k8s:defaulter-gen=TypeMeta +// +k8s:defaulter-gen-input=k8s.io/api/resource/v1alpha1 + +// Package v1alpha1 is the v1alpha1 version of the resource API. +package v1alpha1 // import "k8s.io/kubernetes/pkg/apis/resource/v1alpha1" diff --git a/pkg/apis/resource/v1alpha1/register.go b/pkg/apis/resource/v1alpha1/register.go new file mode 100644 index 00000000000..cd225b259dc --- /dev/null +++ b/pkg/apis/resource/v1alpha1/register.go @@ -0,0 +1,46 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "k8s.io/api/resource/v1alpha1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var ( + localSchemeBuilder = &v1alpha1.SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addDefaultingFuncs, addConversionFuncs) +} + +// TODO: remove these global variables +// GroupName is the group name use in this package +const GroupName = "resource.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/pkg/apis/resource/v1alpha1/zz_generated.conversion.go b/pkg/apis/resource/v1alpha1/zz_generated.conversion.go new file mode 100644 index 00000000000..da556bcae16 --- /dev/null +++ b/pkg/apis/resource/v1alpha1/zz_generated.conversion.go @@ -0,0 +1,668 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + unsafe "unsafe" + + v1 "k8s.io/api/core/v1" + v1alpha1 "k8s.io/api/resource/v1alpha1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + types "k8s.io/apimachinery/pkg/types" + core "k8s.io/kubernetes/pkg/apis/core" + resource "k8s.io/kubernetes/pkg/apis/resource" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*v1alpha1.AllocationResult)(nil), (*resource.AllocationResult)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_AllocationResult_To_resource_AllocationResult(a.(*v1alpha1.AllocationResult), b.(*resource.AllocationResult), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.AllocationResult)(nil), (*v1alpha1.AllocationResult)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_AllocationResult_To_v1alpha1_AllocationResult(a.(*resource.AllocationResult), b.(*v1alpha1.AllocationResult), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.PodScheduling)(nil), (*resource.PodScheduling)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_PodScheduling_To_resource_PodScheduling(a.(*v1alpha1.PodScheduling), b.(*resource.PodScheduling), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.PodScheduling)(nil), (*v1alpha1.PodScheduling)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_PodScheduling_To_v1alpha1_PodScheduling(a.(*resource.PodScheduling), b.(*v1alpha1.PodScheduling), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.PodSchedulingList)(nil), (*resource.PodSchedulingList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_PodSchedulingList_To_resource_PodSchedulingList(a.(*v1alpha1.PodSchedulingList), b.(*resource.PodSchedulingList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.PodSchedulingList)(nil), (*v1alpha1.PodSchedulingList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_PodSchedulingList_To_v1alpha1_PodSchedulingList(a.(*resource.PodSchedulingList), b.(*v1alpha1.PodSchedulingList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.PodSchedulingSpec)(nil), (*resource.PodSchedulingSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_PodSchedulingSpec_To_resource_PodSchedulingSpec(a.(*v1alpha1.PodSchedulingSpec), b.(*resource.PodSchedulingSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.PodSchedulingSpec)(nil), (*v1alpha1.PodSchedulingSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_PodSchedulingSpec_To_v1alpha1_PodSchedulingSpec(a.(*resource.PodSchedulingSpec), b.(*v1alpha1.PodSchedulingSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.PodSchedulingStatus)(nil), (*resource.PodSchedulingStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_PodSchedulingStatus_To_resource_PodSchedulingStatus(a.(*v1alpha1.PodSchedulingStatus), b.(*resource.PodSchedulingStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.PodSchedulingStatus)(nil), (*v1alpha1.PodSchedulingStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_PodSchedulingStatus_To_v1alpha1_PodSchedulingStatus(a.(*resource.PodSchedulingStatus), b.(*v1alpha1.PodSchedulingStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClaim)(nil), (*resource.ResourceClaim)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClaim_To_resource_ResourceClaim(a.(*v1alpha1.ResourceClaim), b.(*resource.ResourceClaim), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClaim)(nil), (*v1alpha1.ResourceClaim)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClaim_To_v1alpha1_ResourceClaim(a.(*resource.ResourceClaim), b.(*v1alpha1.ResourceClaim), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClaimConsumerReference)(nil), (*resource.ResourceClaimConsumerReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClaimConsumerReference_To_resource_ResourceClaimConsumerReference(a.(*v1alpha1.ResourceClaimConsumerReference), b.(*resource.ResourceClaimConsumerReference), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClaimConsumerReference)(nil), (*v1alpha1.ResourceClaimConsumerReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClaimConsumerReference_To_v1alpha1_ResourceClaimConsumerReference(a.(*resource.ResourceClaimConsumerReference), b.(*v1alpha1.ResourceClaimConsumerReference), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClaimList)(nil), (*resource.ResourceClaimList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClaimList_To_resource_ResourceClaimList(a.(*v1alpha1.ResourceClaimList), b.(*resource.ResourceClaimList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClaimList)(nil), (*v1alpha1.ResourceClaimList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClaimList_To_v1alpha1_ResourceClaimList(a.(*resource.ResourceClaimList), b.(*v1alpha1.ResourceClaimList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClaimParametersReference)(nil), (*resource.ResourceClaimParametersReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClaimParametersReference_To_resource_ResourceClaimParametersReference(a.(*v1alpha1.ResourceClaimParametersReference), b.(*resource.ResourceClaimParametersReference), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClaimParametersReference)(nil), (*v1alpha1.ResourceClaimParametersReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClaimParametersReference_To_v1alpha1_ResourceClaimParametersReference(a.(*resource.ResourceClaimParametersReference), b.(*v1alpha1.ResourceClaimParametersReference), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClaimSchedulingStatus)(nil), (*resource.ResourceClaimSchedulingStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClaimSchedulingStatus_To_resource_ResourceClaimSchedulingStatus(a.(*v1alpha1.ResourceClaimSchedulingStatus), b.(*resource.ResourceClaimSchedulingStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClaimSchedulingStatus)(nil), (*v1alpha1.ResourceClaimSchedulingStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClaimSchedulingStatus_To_v1alpha1_ResourceClaimSchedulingStatus(a.(*resource.ResourceClaimSchedulingStatus), b.(*v1alpha1.ResourceClaimSchedulingStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClaimSpec)(nil), (*resource.ResourceClaimSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClaimSpec_To_resource_ResourceClaimSpec(a.(*v1alpha1.ResourceClaimSpec), b.(*resource.ResourceClaimSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClaimSpec)(nil), (*v1alpha1.ResourceClaimSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClaimSpec_To_v1alpha1_ResourceClaimSpec(a.(*resource.ResourceClaimSpec), b.(*v1alpha1.ResourceClaimSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClaimStatus)(nil), (*resource.ResourceClaimStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClaimStatus_To_resource_ResourceClaimStatus(a.(*v1alpha1.ResourceClaimStatus), b.(*resource.ResourceClaimStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClaimStatus)(nil), (*v1alpha1.ResourceClaimStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClaimStatus_To_v1alpha1_ResourceClaimStatus(a.(*resource.ResourceClaimStatus), b.(*v1alpha1.ResourceClaimStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClaimTemplate)(nil), (*resource.ResourceClaimTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClaimTemplate_To_resource_ResourceClaimTemplate(a.(*v1alpha1.ResourceClaimTemplate), b.(*resource.ResourceClaimTemplate), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClaimTemplate)(nil), (*v1alpha1.ResourceClaimTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClaimTemplate_To_v1alpha1_ResourceClaimTemplate(a.(*resource.ResourceClaimTemplate), b.(*v1alpha1.ResourceClaimTemplate), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClaimTemplateList)(nil), (*resource.ResourceClaimTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClaimTemplateList_To_resource_ResourceClaimTemplateList(a.(*v1alpha1.ResourceClaimTemplateList), b.(*resource.ResourceClaimTemplateList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClaimTemplateList)(nil), (*v1alpha1.ResourceClaimTemplateList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClaimTemplateList_To_v1alpha1_ResourceClaimTemplateList(a.(*resource.ResourceClaimTemplateList), b.(*v1alpha1.ResourceClaimTemplateList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClaimTemplateSpec)(nil), (*resource.ResourceClaimTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClaimTemplateSpec_To_resource_ResourceClaimTemplateSpec(a.(*v1alpha1.ResourceClaimTemplateSpec), b.(*resource.ResourceClaimTemplateSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClaimTemplateSpec)(nil), (*v1alpha1.ResourceClaimTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClaimTemplateSpec_To_v1alpha1_ResourceClaimTemplateSpec(a.(*resource.ResourceClaimTemplateSpec), b.(*v1alpha1.ResourceClaimTemplateSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClass)(nil), (*resource.ResourceClass)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClass_To_resource_ResourceClass(a.(*v1alpha1.ResourceClass), b.(*resource.ResourceClass), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClass)(nil), (*v1alpha1.ResourceClass)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClass_To_v1alpha1_ResourceClass(a.(*resource.ResourceClass), b.(*v1alpha1.ResourceClass), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClassList)(nil), (*resource.ResourceClassList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClassList_To_resource_ResourceClassList(a.(*v1alpha1.ResourceClassList), b.(*resource.ResourceClassList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClassList)(nil), (*v1alpha1.ResourceClassList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClassList_To_v1alpha1_ResourceClassList(a.(*resource.ResourceClassList), b.(*v1alpha1.ResourceClassList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ResourceClassParametersReference)(nil), (*resource.ResourceClassParametersReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ResourceClassParametersReference_To_resource_ResourceClassParametersReference(a.(*v1alpha1.ResourceClassParametersReference), b.(*resource.ResourceClassParametersReference), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*resource.ResourceClassParametersReference)(nil), (*v1alpha1.ResourceClassParametersReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_resource_ResourceClassParametersReference_To_v1alpha1_ResourceClassParametersReference(a.(*resource.ResourceClassParametersReference), b.(*v1alpha1.ResourceClassParametersReference), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1alpha1_AllocationResult_To_resource_AllocationResult(in *v1alpha1.AllocationResult, out *resource.AllocationResult, s conversion.Scope) error { + out.ResourceHandle = in.ResourceHandle + out.AvailableOnNodes = (*core.NodeSelector)(unsafe.Pointer(in.AvailableOnNodes)) + out.Shareable = in.Shareable + return nil +} + +// Convert_v1alpha1_AllocationResult_To_resource_AllocationResult is an autogenerated conversion function. +func Convert_v1alpha1_AllocationResult_To_resource_AllocationResult(in *v1alpha1.AllocationResult, out *resource.AllocationResult, s conversion.Scope) error { + return autoConvert_v1alpha1_AllocationResult_To_resource_AllocationResult(in, out, s) +} + +func autoConvert_resource_AllocationResult_To_v1alpha1_AllocationResult(in *resource.AllocationResult, out *v1alpha1.AllocationResult, s conversion.Scope) error { + out.ResourceHandle = in.ResourceHandle + out.AvailableOnNodes = (*v1.NodeSelector)(unsafe.Pointer(in.AvailableOnNodes)) + out.Shareable = in.Shareable + return nil +} + +// Convert_resource_AllocationResult_To_v1alpha1_AllocationResult is an autogenerated conversion function. +func Convert_resource_AllocationResult_To_v1alpha1_AllocationResult(in *resource.AllocationResult, out *v1alpha1.AllocationResult, s conversion.Scope) error { + return autoConvert_resource_AllocationResult_To_v1alpha1_AllocationResult(in, out, s) +} + +func autoConvert_v1alpha1_PodScheduling_To_resource_PodScheduling(in *v1alpha1.PodScheduling, out *resource.PodScheduling, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_PodSchedulingSpec_To_resource_PodSchedulingSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_PodSchedulingStatus_To_resource_PodSchedulingStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_PodScheduling_To_resource_PodScheduling is an autogenerated conversion function. +func Convert_v1alpha1_PodScheduling_To_resource_PodScheduling(in *v1alpha1.PodScheduling, out *resource.PodScheduling, s conversion.Scope) error { + return autoConvert_v1alpha1_PodScheduling_To_resource_PodScheduling(in, out, s) +} + +func autoConvert_resource_PodScheduling_To_v1alpha1_PodScheduling(in *resource.PodScheduling, out *v1alpha1.PodScheduling, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_resource_PodSchedulingSpec_To_v1alpha1_PodSchedulingSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_resource_PodSchedulingStatus_To_v1alpha1_PodSchedulingStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_resource_PodScheduling_To_v1alpha1_PodScheduling is an autogenerated conversion function. +func Convert_resource_PodScheduling_To_v1alpha1_PodScheduling(in *resource.PodScheduling, out *v1alpha1.PodScheduling, s conversion.Scope) error { + return autoConvert_resource_PodScheduling_To_v1alpha1_PodScheduling(in, out, s) +} + +func autoConvert_v1alpha1_PodSchedulingList_To_resource_PodSchedulingList(in *v1alpha1.PodSchedulingList, out *resource.PodSchedulingList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]resource.PodScheduling)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha1_PodSchedulingList_To_resource_PodSchedulingList is an autogenerated conversion function. +func Convert_v1alpha1_PodSchedulingList_To_resource_PodSchedulingList(in *v1alpha1.PodSchedulingList, out *resource.PodSchedulingList, s conversion.Scope) error { + return autoConvert_v1alpha1_PodSchedulingList_To_resource_PodSchedulingList(in, out, s) +} + +func autoConvert_resource_PodSchedulingList_To_v1alpha1_PodSchedulingList(in *resource.PodSchedulingList, out *v1alpha1.PodSchedulingList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1alpha1.PodScheduling)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_resource_PodSchedulingList_To_v1alpha1_PodSchedulingList is an autogenerated conversion function. +func Convert_resource_PodSchedulingList_To_v1alpha1_PodSchedulingList(in *resource.PodSchedulingList, out *v1alpha1.PodSchedulingList, s conversion.Scope) error { + return autoConvert_resource_PodSchedulingList_To_v1alpha1_PodSchedulingList(in, out, s) +} + +func autoConvert_v1alpha1_PodSchedulingSpec_To_resource_PodSchedulingSpec(in *v1alpha1.PodSchedulingSpec, out *resource.PodSchedulingSpec, s conversion.Scope) error { + out.SelectedNode = in.SelectedNode + out.PotentialNodes = *(*[]string)(unsafe.Pointer(&in.PotentialNodes)) + return nil +} + +// Convert_v1alpha1_PodSchedulingSpec_To_resource_PodSchedulingSpec is an autogenerated conversion function. +func Convert_v1alpha1_PodSchedulingSpec_To_resource_PodSchedulingSpec(in *v1alpha1.PodSchedulingSpec, out *resource.PodSchedulingSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_PodSchedulingSpec_To_resource_PodSchedulingSpec(in, out, s) +} + +func autoConvert_resource_PodSchedulingSpec_To_v1alpha1_PodSchedulingSpec(in *resource.PodSchedulingSpec, out *v1alpha1.PodSchedulingSpec, s conversion.Scope) error { + out.SelectedNode = in.SelectedNode + out.PotentialNodes = *(*[]string)(unsafe.Pointer(&in.PotentialNodes)) + return nil +} + +// Convert_resource_PodSchedulingSpec_To_v1alpha1_PodSchedulingSpec is an autogenerated conversion function. +func Convert_resource_PodSchedulingSpec_To_v1alpha1_PodSchedulingSpec(in *resource.PodSchedulingSpec, out *v1alpha1.PodSchedulingSpec, s conversion.Scope) error { + return autoConvert_resource_PodSchedulingSpec_To_v1alpha1_PodSchedulingSpec(in, out, s) +} + +func autoConvert_v1alpha1_PodSchedulingStatus_To_resource_PodSchedulingStatus(in *v1alpha1.PodSchedulingStatus, out *resource.PodSchedulingStatus, s conversion.Scope) error { + out.ResourceClaims = *(*[]resource.ResourceClaimSchedulingStatus)(unsafe.Pointer(&in.ResourceClaims)) + return nil +} + +// Convert_v1alpha1_PodSchedulingStatus_To_resource_PodSchedulingStatus is an autogenerated conversion function. +func Convert_v1alpha1_PodSchedulingStatus_To_resource_PodSchedulingStatus(in *v1alpha1.PodSchedulingStatus, out *resource.PodSchedulingStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_PodSchedulingStatus_To_resource_PodSchedulingStatus(in, out, s) +} + +func autoConvert_resource_PodSchedulingStatus_To_v1alpha1_PodSchedulingStatus(in *resource.PodSchedulingStatus, out *v1alpha1.PodSchedulingStatus, s conversion.Scope) error { + out.ResourceClaims = *(*[]v1alpha1.ResourceClaimSchedulingStatus)(unsafe.Pointer(&in.ResourceClaims)) + return nil +} + +// Convert_resource_PodSchedulingStatus_To_v1alpha1_PodSchedulingStatus is an autogenerated conversion function. +func Convert_resource_PodSchedulingStatus_To_v1alpha1_PodSchedulingStatus(in *resource.PodSchedulingStatus, out *v1alpha1.PodSchedulingStatus, s conversion.Scope) error { + return autoConvert_resource_PodSchedulingStatus_To_v1alpha1_PodSchedulingStatus(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClaim_To_resource_ResourceClaim(in *v1alpha1.ResourceClaim, out *resource.ResourceClaim, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_ResourceClaimSpec_To_resource_ResourceClaimSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_ResourceClaimStatus_To_resource_ResourceClaimStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_ResourceClaim_To_resource_ResourceClaim is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClaim_To_resource_ResourceClaim(in *v1alpha1.ResourceClaim, out *resource.ResourceClaim, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClaim_To_resource_ResourceClaim(in, out, s) +} + +func autoConvert_resource_ResourceClaim_To_v1alpha1_ResourceClaim(in *resource.ResourceClaim, out *v1alpha1.ResourceClaim, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_resource_ResourceClaimSpec_To_v1alpha1_ResourceClaimSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_resource_ResourceClaimStatus_To_v1alpha1_ResourceClaimStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_resource_ResourceClaim_To_v1alpha1_ResourceClaim is an autogenerated conversion function. +func Convert_resource_ResourceClaim_To_v1alpha1_ResourceClaim(in *resource.ResourceClaim, out *v1alpha1.ResourceClaim, s conversion.Scope) error { + return autoConvert_resource_ResourceClaim_To_v1alpha1_ResourceClaim(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClaimConsumerReference_To_resource_ResourceClaimConsumerReference(in *v1alpha1.ResourceClaimConsumerReference, out *resource.ResourceClaimConsumerReference, s conversion.Scope) error { + out.APIGroup = in.APIGroup + out.Resource = in.Resource + out.Name = in.Name + out.UID = types.UID(in.UID) + return nil +} + +// Convert_v1alpha1_ResourceClaimConsumerReference_To_resource_ResourceClaimConsumerReference is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClaimConsumerReference_To_resource_ResourceClaimConsumerReference(in *v1alpha1.ResourceClaimConsumerReference, out *resource.ResourceClaimConsumerReference, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClaimConsumerReference_To_resource_ResourceClaimConsumerReference(in, out, s) +} + +func autoConvert_resource_ResourceClaimConsumerReference_To_v1alpha1_ResourceClaimConsumerReference(in *resource.ResourceClaimConsumerReference, out *v1alpha1.ResourceClaimConsumerReference, s conversion.Scope) error { + out.APIGroup = in.APIGroup + out.Resource = in.Resource + out.Name = in.Name + out.UID = types.UID(in.UID) + return nil +} + +// Convert_resource_ResourceClaimConsumerReference_To_v1alpha1_ResourceClaimConsumerReference is an autogenerated conversion function. +func Convert_resource_ResourceClaimConsumerReference_To_v1alpha1_ResourceClaimConsumerReference(in *resource.ResourceClaimConsumerReference, out *v1alpha1.ResourceClaimConsumerReference, s conversion.Scope) error { + return autoConvert_resource_ResourceClaimConsumerReference_To_v1alpha1_ResourceClaimConsumerReference(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClaimList_To_resource_ResourceClaimList(in *v1alpha1.ResourceClaimList, out *resource.ResourceClaimList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]resource.ResourceClaim)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha1_ResourceClaimList_To_resource_ResourceClaimList is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClaimList_To_resource_ResourceClaimList(in *v1alpha1.ResourceClaimList, out *resource.ResourceClaimList, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClaimList_To_resource_ResourceClaimList(in, out, s) +} + +func autoConvert_resource_ResourceClaimList_To_v1alpha1_ResourceClaimList(in *resource.ResourceClaimList, out *v1alpha1.ResourceClaimList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1alpha1.ResourceClaim)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_resource_ResourceClaimList_To_v1alpha1_ResourceClaimList is an autogenerated conversion function. +func Convert_resource_ResourceClaimList_To_v1alpha1_ResourceClaimList(in *resource.ResourceClaimList, out *v1alpha1.ResourceClaimList, s conversion.Scope) error { + return autoConvert_resource_ResourceClaimList_To_v1alpha1_ResourceClaimList(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClaimParametersReference_To_resource_ResourceClaimParametersReference(in *v1alpha1.ResourceClaimParametersReference, out *resource.ResourceClaimParametersReference, s conversion.Scope) error { + out.APIGroup = in.APIGroup + out.Kind = in.Kind + out.Name = in.Name + return nil +} + +// Convert_v1alpha1_ResourceClaimParametersReference_To_resource_ResourceClaimParametersReference is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClaimParametersReference_To_resource_ResourceClaimParametersReference(in *v1alpha1.ResourceClaimParametersReference, out *resource.ResourceClaimParametersReference, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClaimParametersReference_To_resource_ResourceClaimParametersReference(in, out, s) +} + +func autoConvert_resource_ResourceClaimParametersReference_To_v1alpha1_ResourceClaimParametersReference(in *resource.ResourceClaimParametersReference, out *v1alpha1.ResourceClaimParametersReference, s conversion.Scope) error { + out.APIGroup = in.APIGroup + out.Kind = in.Kind + out.Name = in.Name + return nil +} + +// Convert_resource_ResourceClaimParametersReference_To_v1alpha1_ResourceClaimParametersReference is an autogenerated conversion function. +func Convert_resource_ResourceClaimParametersReference_To_v1alpha1_ResourceClaimParametersReference(in *resource.ResourceClaimParametersReference, out *v1alpha1.ResourceClaimParametersReference, s conversion.Scope) error { + return autoConvert_resource_ResourceClaimParametersReference_To_v1alpha1_ResourceClaimParametersReference(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClaimSchedulingStatus_To_resource_ResourceClaimSchedulingStatus(in *v1alpha1.ResourceClaimSchedulingStatus, out *resource.ResourceClaimSchedulingStatus, s conversion.Scope) error { + out.Name = in.Name + out.UnsuitableNodes = *(*[]string)(unsafe.Pointer(&in.UnsuitableNodes)) + return nil +} + +// Convert_v1alpha1_ResourceClaimSchedulingStatus_To_resource_ResourceClaimSchedulingStatus is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClaimSchedulingStatus_To_resource_ResourceClaimSchedulingStatus(in *v1alpha1.ResourceClaimSchedulingStatus, out *resource.ResourceClaimSchedulingStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClaimSchedulingStatus_To_resource_ResourceClaimSchedulingStatus(in, out, s) +} + +func autoConvert_resource_ResourceClaimSchedulingStatus_To_v1alpha1_ResourceClaimSchedulingStatus(in *resource.ResourceClaimSchedulingStatus, out *v1alpha1.ResourceClaimSchedulingStatus, s conversion.Scope) error { + out.Name = in.Name + out.UnsuitableNodes = *(*[]string)(unsafe.Pointer(&in.UnsuitableNodes)) + return nil +} + +// Convert_resource_ResourceClaimSchedulingStatus_To_v1alpha1_ResourceClaimSchedulingStatus is an autogenerated conversion function. +func Convert_resource_ResourceClaimSchedulingStatus_To_v1alpha1_ResourceClaimSchedulingStatus(in *resource.ResourceClaimSchedulingStatus, out *v1alpha1.ResourceClaimSchedulingStatus, s conversion.Scope) error { + return autoConvert_resource_ResourceClaimSchedulingStatus_To_v1alpha1_ResourceClaimSchedulingStatus(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClaimSpec_To_resource_ResourceClaimSpec(in *v1alpha1.ResourceClaimSpec, out *resource.ResourceClaimSpec, s conversion.Scope) error { + out.ResourceClassName = in.ResourceClassName + out.ParametersRef = (*resource.ResourceClaimParametersReference)(unsafe.Pointer(in.ParametersRef)) + out.AllocationMode = resource.AllocationMode(in.AllocationMode) + return nil +} + +// Convert_v1alpha1_ResourceClaimSpec_To_resource_ResourceClaimSpec is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClaimSpec_To_resource_ResourceClaimSpec(in *v1alpha1.ResourceClaimSpec, out *resource.ResourceClaimSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClaimSpec_To_resource_ResourceClaimSpec(in, out, s) +} + +func autoConvert_resource_ResourceClaimSpec_To_v1alpha1_ResourceClaimSpec(in *resource.ResourceClaimSpec, out *v1alpha1.ResourceClaimSpec, s conversion.Scope) error { + out.ResourceClassName = in.ResourceClassName + out.ParametersRef = (*v1alpha1.ResourceClaimParametersReference)(unsafe.Pointer(in.ParametersRef)) + out.AllocationMode = v1alpha1.AllocationMode(in.AllocationMode) + return nil +} + +// Convert_resource_ResourceClaimSpec_To_v1alpha1_ResourceClaimSpec is an autogenerated conversion function. +func Convert_resource_ResourceClaimSpec_To_v1alpha1_ResourceClaimSpec(in *resource.ResourceClaimSpec, out *v1alpha1.ResourceClaimSpec, s conversion.Scope) error { + return autoConvert_resource_ResourceClaimSpec_To_v1alpha1_ResourceClaimSpec(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClaimStatus_To_resource_ResourceClaimStatus(in *v1alpha1.ResourceClaimStatus, out *resource.ResourceClaimStatus, s conversion.Scope) error { + out.DriverName = in.DriverName + out.Allocation = (*resource.AllocationResult)(unsafe.Pointer(in.Allocation)) + out.ReservedFor = *(*[]resource.ResourceClaimConsumerReference)(unsafe.Pointer(&in.ReservedFor)) + out.DeallocationRequested = in.DeallocationRequested + return nil +} + +// Convert_v1alpha1_ResourceClaimStatus_To_resource_ResourceClaimStatus is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClaimStatus_To_resource_ResourceClaimStatus(in *v1alpha1.ResourceClaimStatus, out *resource.ResourceClaimStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClaimStatus_To_resource_ResourceClaimStatus(in, out, s) +} + +func autoConvert_resource_ResourceClaimStatus_To_v1alpha1_ResourceClaimStatus(in *resource.ResourceClaimStatus, out *v1alpha1.ResourceClaimStatus, s conversion.Scope) error { + out.DriverName = in.DriverName + out.Allocation = (*v1alpha1.AllocationResult)(unsafe.Pointer(in.Allocation)) + out.ReservedFor = *(*[]v1alpha1.ResourceClaimConsumerReference)(unsafe.Pointer(&in.ReservedFor)) + out.DeallocationRequested = in.DeallocationRequested + return nil +} + +// Convert_resource_ResourceClaimStatus_To_v1alpha1_ResourceClaimStatus is an autogenerated conversion function. +func Convert_resource_ResourceClaimStatus_To_v1alpha1_ResourceClaimStatus(in *resource.ResourceClaimStatus, out *v1alpha1.ResourceClaimStatus, s conversion.Scope) error { + return autoConvert_resource_ResourceClaimStatus_To_v1alpha1_ResourceClaimStatus(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClaimTemplate_To_resource_ResourceClaimTemplate(in *v1alpha1.ResourceClaimTemplate, out *resource.ResourceClaimTemplate, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_ResourceClaimTemplateSpec_To_resource_ResourceClaimTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_ResourceClaimTemplate_To_resource_ResourceClaimTemplate is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClaimTemplate_To_resource_ResourceClaimTemplate(in *v1alpha1.ResourceClaimTemplate, out *resource.ResourceClaimTemplate, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClaimTemplate_To_resource_ResourceClaimTemplate(in, out, s) +} + +func autoConvert_resource_ResourceClaimTemplate_To_v1alpha1_ResourceClaimTemplate(in *resource.ResourceClaimTemplate, out *v1alpha1.ResourceClaimTemplate, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_resource_ResourceClaimTemplateSpec_To_v1alpha1_ResourceClaimTemplateSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_resource_ResourceClaimTemplate_To_v1alpha1_ResourceClaimTemplate is an autogenerated conversion function. +func Convert_resource_ResourceClaimTemplate_To_v1alpha1_ResourceClaimTemplate(in *resource.ResourceClaimTemplate, out *v1alpha1.ResourceClaimTemplate, s conversion.Scope) error { + return autoConvert_resource_ResourceClaimTemplate_To_v1alpha1_ResourceClaimTemplate(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClaimTemplateList_To_resource_ResourceClaimTemplateList(in *v1alpha1.ResourceClaimTemplateList, out *resource.ResourceClaimTemplateList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]resource.ResourceClaimTemplate)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha1_ResourceClaimTemplateList_To_resource_ResourceClaimTemplateList is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClaimTemplateList_To_resource_ResourceClaimTemplateList(in *v1alpha1.ResourceClaimTemplateList, out *resource.ResourceClaimTemplateList, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClaimTemplateList_To_resource_ResourceClaimTemplateList(in, out, s) +} + +func autoConvert_resource_ResourceClaimTemplateList_To_v1alpha1_ResourceClaimTemplateList(in *resource.ResourceClaimTemplateList, out *v1alpha1.ResourceClaimTemplateList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1alpha1.ResourceClaimTemplate)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_resource_ResourceClaimTemplateList_To_v1alpha1_ResourceClaimTemplateList is an autogenerated conversion function. +func Convert_resource_ResourceClaimTemplateList_To_v1alpha1_ResourceClaimTemplateList(in *resource.ResourceClaimTemplateList, out *v1alpha1.ResourceClaimTemplateList, s conversion.Scope) error { + return autoConvert_resource_ResourceClaimTemplateList_To_v1alpha1_ResourceClaimTemplateList(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClaimTemplateSpec_To_resource_ResourceClaimTemplateSpec(in *v1alpha1.ResourceClaimTemplateSpec, out *resource.ResourceClaimTemplateSpec, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_ResourceClaimSpec_To_resource_ResourceClaimSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_ResourceClaimTemplateSpec_To_resource_ResourceClaimTemplateSpec is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClaimTemplateSpec_To_resource_ResourceClaimTemplateSpec(in *v1alpha1.ResourceClaimTemplateSpec, out *resource.ResourceClaimTemplateSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClaimTemplateSpec_To_resource_ResourceClaimTemplateSpec(in, out, s) +} + +func autoConvert_resource_ResourceClaimTemplateSpec_To_v1alpha1_ResourceClaimTemplateSpec(in *resource.ResourceClaimTemplateSpec, out *v1alpha1.ResourceClaimTemplateSpec, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_resource_ResourceClaimSpec_To_v1alpha1_ResourceClaimSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_resource_ResourceClaimTemplateSpec_To_v1alpha1_ResourceClaimTemplateSpec is an autogenerated conversion function. +func Convert_resource_ResourceClaimTemplateSpec_To_v1alpha1_ResourceClaimTemplateSpec(in *resource.ResourceClaimTemplateSpec, out *v1alpha1.ResourceClaimTemplateSpec, s conversion.Scope) error { + return autoConvert_resource_ResourceClaimTemplateSpec_To_v1alpha1_ResourceClaimTemplateSpec(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClass_To_resource_ResourceClass(in *v1alpha1.ResourceClass, out *resource.ResourceClass, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + out.DriverName = in.DriverName + out.ParametersRef = (*resource.ResourceClassParametersReference)(unsafe.Pointer(in.ParametersRef)) + out.SuitableNodes = (*core.NodeSelector)(unsafe.Pointer(in.SuitableNodes)) + return nil +} + +// Convert_v1alpha1_ResourceClass_To_resource_ResourceClass is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClass_To_resource_ResourceClass(in *v1alpha1.ResourceClass, out *resource.ResourceClass, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClass_To_resource_ResourceClass(in, out, s) +} + +func autoConvert_resource_ResourceClass_To_v1alpha1_ResourceClass(in *resource.ResourceClass, out *v1alpha1.ResourceClass, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + out.DriverName = in.DriverName + out.ParametersRef = (*v1alpha1.ResourceClassParametersReference)(unsafe.Pointer(in.ParametersRef)) + out.SuitableNodes = (*v1.NodeSelector)(unsafe.Pointer(in.SuitableNodes)) + return nil +} + +// Convert_resource_ResourceClass_To_v1alpha1_ResourceClass is an autogenerated conversion function. +func Convert_resource_ResourceClass_To_v1alpha1_ResourceClass(in *resource.ResourceClass, out *v1alpha1.ResourceClass, s conversion.Scope) error { + return autoConvert_resource_ResourceClass_To_v1alpha1_ResourceClass(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClassList_To_resource_ResourceClassList(in *v1alpha1.ResourceClassList, out *resource.ResourceClassList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]resource.ResourceClass)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha1_ResourceClassList_To_resource_ResourceClassList is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClassList_To_resource_ResourceClassList(in *v1alpha1.ResourceClassList, out *resource.ResourceClassList, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClassList_To_resource_ResourceClassList(in, out, s) +} + +func autoConvert_resource_ResourceClassList_To_v1alpha1_ResourceClassList(in *resource.ResourceClassList, out *v1alpha1.ResourceClassList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1alpha1.ResourceClass)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_resource_ResourceClassList_To_v1alpha1_ResourceClassList is an autogenerated conversion function. +func Convert_resource_ResourceClassList_To_v1alpha1_ResourceClassList(in *resource.ResourceClassList, out *v1alpha1.ResourceClassList, s conversion.Scope) error { + return autoConvert_resource_ResourceClassList_To_v1alpha1_ResourceClassList(in, out, s) +} + +func autoConvert_v1alpha1_ResourceClassParametersReference_To_resource_ResourceClassParametersReference(in *v1alpha1.ResourceClassParametersReference, out *resource.ResourceClassParametersReference, s conversion.Scope) error { + out.APIGroup = in.APIGroup + out.Kind = in.Kind + out.Name = in.Name + out.Namespace = in.Namespace + return nil +} + +// Convert_v1alpha1_ResourceClassParametersReference_To_resource_ResourceClassParametersReference is an autogenerated conversion function. +func Convert_v1alpha1_ResourceClassParametersReference_To_resource_ResourceClassParametersReference(in *v1alpha1.ResourceClassParametersReference, out *resource.ResourceClassParametersReference, s conversion.Scope) error { + return autoConvert_v1alpha1_ResourceClassParametersReference_To_resource_ResourceClassParametersReference(in, out, s) +} + +func autoConvert_resource_ResourceClassParametersReference_To_v1alpha1_ResourceClassParametersReference(in *resource.ResourceClassParametersReference, out *v1alpha1.ResourceClassParametersReference, s conversion.Scope) error { + out.APIGroup = in.APIGroup + out.Kind = in.Kind + out.Name = in.Name + out.Namespace = in.Namespace + return nil +} + +// Convert_resource_ResourceClassParametersReference_To_v1alpha1_ResourceClassParametersReference is an autogenerated conversion function. +func Convert_resource_ResourceClassParametersReference_To_v1alpha1_ResourceClassParametersReference(in *resource.ResourceClassParametersReference, out *v1alpha1.ResourceClassParametersReference, s conversion.Scope) error { + return autoConvert_resource_ResourceClassParametersReference_To_v1alpha1_ResourceClassParametersReference(in, out, s) +} diff --git a/pkg/apis/resource/v1alpha1/zz_generated.defaults.go b/pkg/apis/resource/v1alpha1/zz_generated.defaults.go new file mode 100644 index 00000000000..e93e4a988a9 --- /dev/null +++ b/pkg/apis/resource/v1alpha1/zz_generated.defaults.go @@ -0,0 +1,62 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "k8s.io/api/resource/v1alpha1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + scheme.AddTypeDefaultingFunc(&v1alpha1.ResourceClaim{}, func(obj interface{}) { SetObjectDefaults_ResourceClaim(obj.(*v1alpha1.ResourceClaim)) }) + scheme.AddTypeDefaultingFunc(&v1alpha1.ResourceClaimList{}, func(obj interface{}) { SetObjectDefaults_ResourceClaimList(obj.(*v1alpha1.ResourceClaimList)) }) + scheme.AddTypeDefaultingFunc(&v1alpha1.ResourceClaimTemplate{}, func(obj interface{}) { SetObjectDefaults_ResourceClaimTemplate(obj.(*v1alpha1.ResourceClaimTemplate)) }) + scheme.AddTypeDefaultingFunc(&v1alpha1.ResourceClaimTemplateList{}, func(obj interface{}) { + SetObjectDefaults_ResourceClaimTemplateList(obj.(*v1alpha1.ResourceClaimTemplateList)) + }) + return nil +} + +func SetObjectDefaults_ResourceClaim(in *v1alpha1.ResourceClaim) { + SetDefaults_ResourceClaimSpec(&in.Spec) +} + +func SetObjectDefaults_ResourceClaimList(in *v1alpha1.ResourceClaimList) { + for i := range in.Items { + a := &in.Items[i] + SetObjectDefaults_ResourceClaim(a) + } +} + +func SetObjectDefaults_ResourceClaimTemplate(in *v1alpha1.ResourceClaimTemplate) { + SetDefaults_ResourceClaimSpec(&in.Spec.Spec) +} + +func SetObjectDefaults_ResourceClaimTemplateList(in *v1alpha1.ResourceClaimTemplateList) { + for i := range in.Items { + a := &in.Items[i] + SetObjectDefaults_ResourceClaimTemplate(a) + } +} diff --git a/pkg/apis/resource/validation/validation.go b/pkg/apis/resource/validation/validation.go new file mode 100644 index 00000000000..fcbf8c55c18 --- /dev/null +++ b/pkg/apis/resource/validation/validation.go @@ -0,0 +1,310 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/util/validation/field" + corevalidation "k8s.io/kubernetes/pkg/apis/core/validation" + "k8s.io/kubernetes/pkg/apis/resource" +) + +// validateResourceClaimName can be used to check whether the given +// name for a ResourceClaim is valid. +var validateResourceClaimName = apimachineryvalidation.NameIsDNSSubdomain + +// validateResourceClaimTemplateName can be used to check whether the given +// name for a ResourceClaimTemplate is valid. +var validateResourceClaimTemplateName = apimachineryvalidation.NameIsDNSSubdomain + +// validateResourceDriverName reuses the validation of a CSI driver because +// the allowed values are exactly the same. +var validateResourceDriverName = corevalidation.ValidateCSIDriverName + +// ValidateClaim validates a ResourceClaim. +func ValidateClaim(resourceClaim *resource.ResourceClaim) field.ErrorList { + allErrs := corevalidation.ValidateObjectMeta(&resourceClaim.ObjectMeta, true, validateResourceClaimName, field.NewPath("metadata")) + allErrs = append(allErrs, validateResourceClaimSpec(&resourceClaim.Spec, field.NewPath("spec"))...) + return allErrs +} + +func validateResourceClaimSpec(spec *resource.ResourceClaimSpec, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + for _, msg := range corevalidation.ValidateClassName(spec.ResourceClassName, false) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("resourceClassName"), spec.ResourceClassName, msg)) + } + allErrs = append(allErrs, validateResourceClaimParameters(spec.ParametersRef, fldPath.Child("parametersRef"))...) + if !supportedAllocationModes.Has(string(spec.AllocationMode)) { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("allocationMode"), spec.AllocationMode, supportedAllocationModes.List())) + } + return allErrs +} + +var supportedAllocationModes = sets.NewString(string(resource.AllocationModeImmediate), string(resource.AllocationModeWaitForFirstConsumer)) + +// It would have been nice to use Go generics to reuse the same validation +// function for Kind and Name in both types, but generics cannot be used to +// access common fields in structs. + +func validateResourceClaimParameters(ref *resource.ResourceClaimParametersReference, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + if ref != nil { + if ref.Kind == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("kind"), "")) + } + if ref.Name == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) + } + } + return allErrs +} + +func validateClassParameters(ref *resource.ResourceClassParametersReference, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + if ref != nil { + if ref.Kind == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("kind"), "")) + } + if ref.Name == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) + } + if ref.Namespace != "" { + for _, msg := range apimachineryvalidation.ValidateNamespaceName(ref.Namespace, false) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), ref.Namespace, msg)) + } + } + } + return allErrs +} + +// ValidateClass validates a ResourceClass. +func ValidateClass(resourceClass *resource.ResourceClass) field.ErrorList { + allErrs := corevalidation.ValidateObjectMeta(&resourceClass.ObjectMeta, false, corevalidation.ValidateClassName, field.NewPath("metadata")) + allErrs = append(allErrs, validateResourceDriverName(resourceClass.DriverName, field.NewPath("driverName"))...) + allErrs = append(allErrs, validateClassParameters(resourceClass.ParametersRef, field.NewPath("parametersRef"))...) + if resourceClass.SuitableNodes != nil { + allErrs = append(allErrs, corevalidation.ValidateNodeSelector(resourceClass.SuitableNodes, field.NewPath("suitableNodes"))...) + } + + return allErrs +} + +// ValidateClassUpdate tests if an update to ResourceClass is valid. +func ValidateClassUpdate(resourceClass, oldClass *resource.ResourceClass) field.ErrorList { + allErrs := corevalidation.ValidateObjectMetaUpdate(&resourceClass.ObjectMeta, &oldClass.ObjectMeta, field.NewPath("metadata")) + allErrs = append(allErrs, ValidateClass(resourceClass)...) + return allErrs +} + +// ValidateClaimUpdate tests if an update to ResourceClaim is valid. +func ValidateClaimUpdate(resourceClaim, oldClaim *resource.ResourceClaim) field.ErrorList { + allErrs := corevalidation.ValidateObjectMetaUpdate(&resourceClaim.ObjectMeta, &oldClaim.ObjectMeta, field.NewPath("metadata")) + allErrs = append(allErrs, apimachineryvalidation.ValidateImmutableField(resourceClaim.Spec, oldClaim.Spec, field.NewPath("spec"))...) + allErrs = append(allErrs, ValidateClaim(resourceClaim)...) + return allErrs +} + +// ValidateClaimStatusUpdate tests if an update to the status of a ResourceClaim is valid. +func ValidateClaimStatusUpdate(resourceClaim, oldClaim *resource.ResourceClaim) field.ErrorList { + allErrs := corevalidation.ValidateObjectMetaUpdate(&resourceClaim.ObjectMeta, &oldClaim.ObjectMeta, field.NewPath("metadata")) + fldPath := field.NewPath("status") + // The name might not be set yet. + if resourceClaim.Status.DriverName != "" { + allErrs = append(allErrs, validateResourceDriverName(resourceClaim.Status.DriverName, fldPath.Child("driverName"))...) + } else if resourceClaim.Status.Allocation != nil { + allErrs = append(allErrs, field.Required(fldPath.Child("driverName"), "must be specified when `allocation` is set")) + } + + allErrs = append(allErrs, validateAllocationResult(resourceClaim.Status.Allocation, fldPath.Child("allocation"))...) + allErrs = append(allErrs, validateSliceIsASet(resourceClaim.Status.ReservedFor, resource.ResourceClaimReservedForMaxSize, + validateResourceClaimUserReference, fldPath.Child("reservedFor"))...) + + // Now check for invariants that must be valid for a ResourceClaim. + if len(resourceClaim.Status.ReservedFor) > 0 { + if resourceClaim.Status.Allocation == nil { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("reservedFor"), "may not be specified when `allocated` is not set")) + } else { + if !resourceClaim.Status.Allocation.Shareable && len(resourceClaim.Status.ReservedFor) > 1 { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("reservedFor"), "may not be reserved more than once")) + } + // Items may be removed from ReservedFor while the claim is meant to be deallocated, + // but not added. + if resourceClaim.DeletionTimestamp != nil || resourceClaim.Status.DeallocationRequested { + oldSet := sets.New(oldClaim.Status.ReservedFor...) + newSet := sets.New(resourceClaim.Status.ReservedFor...) + newItems := newSet.Difference(oldSet) + if len(newItems) > 0 { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("reservedFor"), "new entries may not be added while `deallocationRequested` or `deletionTimestamp` are set")) + } + } + } + } + + if !oldClaim.Status.DeallocationRequested && + resourceClaim.Status.DeallocationRequested && + len(resourceClaim.Status.ReservedFor) > 0 { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("deallocationRequested"), "deallocation cannot be requested while `reservedFor` is set")) + } + + if resourceClaim.Status.Allocation == nil && + resourceClaim.Status.DeallocationRequested { + // Either one or the other field was modified incorrectly. + // For the sake of simplicity this only reports the invalid + // end result. + allErrs = append(allErrs, field.Forbidden(fldPath, "`allocation` must be set when `deallocationRequested` is set")) + } + + // Once deallocation has been requested, that request cannot be removed + // anymore because the deallocation may already have started. The field + // can only get reset by the driver together with removing the + // allocation. + if oldClaim.Status.DeallocationRequested && + !resourceClaim.Status.DeallocationRequested && + resourceClaim.Status.Allocation != nil { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("deallocationRequested"), "may not be cleared when `allocation` is set")) + } + + return allErrs +} + +func validateAllocationResult(allocation *resource.AllocationResult, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + if allocation != nil { + if len(allocation.ResourceHandle) > resource.ResourceHandleMaxSize { + allErrs = append(allErrs, field.TooLongMaxLength(fldPath.Child("resourceHandle"), len(allocation.ResourceHandle), resource.ResourceHandleMaxSize)) + } + if allocation.AvailableOnNodes != nil { + allErrs = append(allErrs, corevalidation.ValidateNodeSelector(allocation.AvailableOnNodes, fldPath.Child("availableOnNodes"))...) + } + } + return allErrs +} + +func validateResourceClaimUserReference(ref resource.ResourceClaimConsumerReference, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + if ref.Resource == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("resource"), "")) + } + if ref.Name == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) + } + if ref.UID == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("uid"), "")) + } + return allErrs +} + +// validateSliceIsASet ensures that a slice contains no duplicates and does not exceed a certain maximum size. +func validateSliceIsASet[T comparable](slice []T, maxSize int, validateItem func(item T, fldPath *field.Path) field.ErrorList, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + allItems := sets.New[T]() + for i, item := range slice { + idxPath := fldPath.Index(i) + if allItems.Has(item) { + allErrs = append(allErrs, field.Duplicate(idxPath, item)) + } else { + allErrs = append(allErrs, validateItem(item, idxPath)...) + allItems.Insert(item) + } + } + if len(slice) > maxSize { + // Dumping the entire field into the error message is likely to be too long, + // in particular when it is already beyond the maximum size. Instead this + // just shows the number of entries. + allErrs = append(allErrs, field.TooLongMaxLength(fldPath, len(slice), maxSize)) + } + return allErrs +} + +// ValidatePodScheduling validates a PodScheduling. +func ValidatePodScheduling(resourceClaim *resource.PodScheduling) field.ErrorList { + allErrs := corevalidation.ValidateObjectMeta(&resourceClaim.ObjectMeta, true, corevalidation.ValidatePodName, field.NewPath("metadata")) + allErrs = append(allErrs, validatePodSchedulingSpec(&resourceClaim.Spec, field.NewPath("spec"))...) + return allErrs +} + +func validatePodSchedulingSpec(spec *resource.PodSchedulingSpec, fldPath *field.Path) field.ErrorList { + allErrs := validateSliceIsASet(spec.PotentialNodes, resource.PodSchedulingNodeListMaxSize, validateNodeName, fldPath.Child("potentialNodes")) + return allErrs +} + +// ValidatePodSchedulingUpdate tests if an update to PodScheduling is valid. +func ValidatePodSchedulingUpdate(resourceClaim, oldPodScheduling *resource.PodScheduling) field.ErrorList { + allErrs := corevalidation.ValidateObjectMetaUpdate(&resourceClaim.ObjectMeta, &oldPodScheduling.ObjectMeta, field.NewPath("metadata")) + allErrs = append(allErrs, ValidatePodScheduling(resourceClaim)...) + return allErrs +} + +// ValidatePodSchedulingStatusUpdate tests if an update to the status of a PodScheduling is valid. +func ValidatePodSchedulingStatusUpdate(resourceClaim, oldPodScheduling *resource.PodScheduling) field.ErrorList { + allErrs := corevalidation.ValidateObjectMetaUpdate(&resourceClaim.ObjectMeta, &oldPodScheduling.ObjectMeta, field.NewPath("metadata")) + allErrs = append(allErrs, validatePodSchedulingStatus(&resourceClaim.Status, field.NewPath("status"))...) + return allErrs +} + +func validatePodSchedulingStatus(status *resource.PodSchedulingStatus, fldPath *field.Path) field.ErrorList { + return validatePodSchedulingClaims(status.ResourceClaims, fldPath.Child("claims")) +} + +func validatePodSchedulingClaims(claimStatuses []resource.ResourceClaimSchedulingStatus, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + names := sets.NewString() + for i, claimStatus := range claimStatuses { + allErrs = append(allErrs, validatePodSchedulingClaim(claimStatus, fldPath.Index(i))...) + if names.Has(claimStatus.Name) { + allErrs = append(allErrs, field.Duplicate(fldPath.Index(i), claimStatus.Name)) + } else { + names.Insert(claimStatus.Name) + } + } + return allErrs +} + +func validatePodSchedulingClaim(status resource.ResourceClaimSchedulingStatus, fldPath *field.Path) field.ErrorList { + allErrs := validateSliceIsASet(status.UnsuitableNodes, resource.PodSchedulingNodeListMaxSize, validateNodeName, fldPath.Child("unsuitableNodes")) + return allErrs +} + +// ValidateClaimTemplace validates a ResourceClaimTemplate. +func ValidateClaimTemplate(template *resource.ResourceClaimTemplate) field.ErrorList { + allErrs := corevalidation.ValidateObjectMeta(&template.ObjectMeta, true, validateResourceClaimTemplateName, field.NewPath("metadata")) + allErrs = append(allErrs, validateResourceClaimTemplateSpec(&template.Spec, field.NewPath("spec"))...) + return allErrs +} + +func validateResourceClaimTemplateSpec(spec *resource.ResourceClaimTemplateSpec, fldPath *field.Path) field.ErrorList { + allErrs := corevalidation.ValidateTemplateObjectMeta(&spec.ObjectMeta, fldPath.Child("metadata")) + allErrs = append(allErrs, validateResourceClaimSpec(&spec.Spec, fldPath.Child("spec"))...) + return allErrs +} + +// ValidateClaimTemplateUpdate tests if an update to template is valid. +func ValidateClaimTemplateUpdate(template, oldTemplate *resource.ResourceClaimTemplate) field.ErrorList { + allErrs := corevalidation.ValidateObjectMetaUpdate(&template.ObjectMeta, &oldTemplate.ObjectMeta, field.NewPath("metadata")) + allErrs = append(allErrs, apimachineryvalidation.ValidateImmutableField(template.Spec, oldTemplate.Spec, field.NewPath("spec"))...) + allErrs = append(allErrs, ValidateClaimTemplate(template)...) + return allErrs +} + +func validateNodeName(name string, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + for _, msg := range corevalidation.ValidateNodeName(name, false) { + allErrs = append(allErrs, field.Invalid(fldPath, name, msg)) + } + return allErrs +} diff --git a/pkg/apis/resource/validation/validation_podscheduling_test.go b/pkg/apis/resource/validation/validation_podscheduling_test.go new file mode 100644 index 00000000000..30193eb5a3a --- /dev/null +++ b/pkg/apis/resource/validation/validation_podscheduling_test.go @@ -0,0 +1,338 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/utils/pointer" +) + +func testPodScheduling(name, namespace string, spec resource.PodSchedulingSpec) *resource.PodScheduling { + return &resource.PodScheduling{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: spec, + } +} + +func TestValidatePodScheduling(t *testing.T) { + goodName := "foo" + goodNS := "ns" + goodPodSchedulingSpec := resource.PodSchedulingSpec{} + now := metav1.Now() + badName := "!@#$%^" + badValue := "spaces not allowed" + + scenarios := map[string]struct { + scheduling *resource.PodScheduling + wantFailures field.ErrorList + }{ + "good-scheduling": { + scheduling: testPodScheduling(goodName, goodNS, goodPodSchedulingSpec), + }, + "missing-name": { + wantFailures: field.ErrorList{field.Required(field.NewPath("metadata", "name"), "name or generateName is required")}, + scheduling: testPodScheduling("", goodNS, goodPodSchedulingSpec), + }, + "bad-name": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("metadata", "name"), badName, "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")}, + scheduling: testPodScheduling(badName, goodNS, goodPodSchedulingSpec), + }, + "missing-namespace": { + wantFailures: field.ErrorList{field.Required(field.NewPath("metadata", "namespace"), "")}, + scheduling: testPodScheduling(goodName, "", goodPodSchedulingSpec), + }, + "generate-name": { + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.GenerateName = "pvc-" + return scheduling + }(), + }, + "uid": { + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.UID = "ac051fac-2ead-46d9-b8b4-4e0fbeb7455d" + return scheduling + }(), + }, + "resource-version": { + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.ResourceVersion = "1" + return scheduling + }(), + }, + "generation": { + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.Generation = 100 + return scheduling + }(), + }, + "creation-timestamp": { + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.CreationTimestamp = now + return scheduling + }(), + }, + "deletion-grace-period-seconds": { + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.DeletionGracePeriodSeconds = pointer.Int64(10) + return scheduling + }(), + }, + "owner-references": { + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.OwnerReferences = []metav1.OwnerReference{ + { + APIVersion: "v1", + Kind: "pod", + Name: "foo", + UID: "ac051fac-2ead-46d9-b8b4-4e0fbeb7455d", + }, + } + return scheduling + }(), + }, + "finalizers": { + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.Finalizers = []string{ + "example.com/foo", + } + return scheduling + }(), + }, + "managed-fields": { + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.ManagedFields = []metav1.ManagedFieldsEntry{ + { + FieldsType: "FieldsV1", + Operation: "Apply", + APIVersion: "apps/v1", + Manager: "foo", + }, + } + return scheduling + }(), + }, + "good-labels": { + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.Labels = map[string]string{ + "apps.kubernetes.io/name": "test", + } + return scheduling + }(), + }, + "bad-labels": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("metadata", "labels"), badValue, "a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyValue', or 'my_value', or '12345', regex used for validation is '(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?')")}, + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.Labels = map[string]string{ + "hello-world": badValue, + } + return scheduling + }(), + }, + "good-annotations": { + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.Annotations = map[string]string{ + "foo": "bar", + } + return scheduling + }(), + }, + "bad-annotations": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("metadata", "annotations"), badName, "name part must consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]')")}, + scheduling: func() *resource.PodScheduling { + scheduling := testPodScheduling(goodName, goodNS, goodPodSchedulingSpec) + scheduling.Annotations = map[string]string{ + badName: "hello world", + } + return scheduling + }(), + }, + } + + for name, scenario := range scenarios { + t.Run(name, func(t *testing.T) { + errs := ValidatePodScheduling(scenario.scheduling) + assert.Equal(t, scenario.wantFailures, errs) + }) + } +} + +func TestValidatePodSchedulingUpdate(t *testing.T) { + validScheduling := testPodScheduling("foo", "ns", resource.PodSchedulingSpec{}) + badName := "!@#$%^" + + scenarios := map[string]struct { + oldScheduling *resource.PodScheduling + update func(scheduling *resource.PodScheduling) *resource.PodScheduling + wantFailures field.ErrorList + }{ + "valid-no-op-update": { + oldScheduling: validScheduling, + update: func(scheduling *resource.PodScheduling) *resource.PodScheduling { return scheduling }, + }, + "add-selected-node": { + oldScheduling: validScheduling, + update: func(scheduling *resource.PodScheduling) *resource.PodScheduling { + scheduling.Spec.SelectedNode = "worker1" + return scheduling + }, + }, + "add-potential-nodes": { + oldScheduling: validScheduling, + update: func(scheduling *resource.PodScheduling) *resource.PodScheduling { + for i := 0; i < resource.PodSchedulingNodeListMaxSize; i++ { + scheduling.Spec.PotentialNodes = append(scheduling.Spec.PotentialNodes, fmt.Sprintf("worker%d", i)) + } + return scheduling + }, + }, + "invalid-potential-nodes-too-long": { + wantFailures: field.ErrorList{field.TooLongMaxLength(field.NewPath("spec", "potentialNodes"), 129, resource.PodSchedulingNodeListMaxSize)}, + oldScheduling: validScheduling, + update: func(scheduling *resource.PodScheduling) *resource.PodScheduling { + for i := 0; i < resource.PodSchedulingNodeListMaxSize+1; i++ { + scheduling.Spec.PotentialNodes = append(scheduling.Spec.PotentialNodes, fmt.Sprintf("worker%d", i)) + } + return scheduling + }, + }, + "invalid-potential-nodes-name": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("spec", "potentialNodes").Index(0), badName, "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")}, + oldScheduling: validScheduling, + update: func(scheduling *resource.PodScheduling) *resource.PodScheduling { + scheduling.Spec.PotentialNodes = append(scheduling.Spec.PotentialNodes, badName) + return scheduling + }, + }, + } + + for name, scenario := range scenarios { + t.Run(name, func(t *testing.T) { + scenario.oldScheduling.ResourceVersion = "1" + errs := ValidatePodSchedulingUpdate(scenario.update(scenario.oldScheduling.DeepCopy()), scenario.oldScheduling) + assert.Equal(t, scenario.wantFailures, errs) + }) + } +} + +func TestValidatePodSchedulingStatusUpdate(t *testing.T) { + validScheduling := testPodScheduling("foo", "ns", resource.PodSchedulingSpec{}) + badName := "!@#$%^" + + scenarios := map[string]struct { + oldScheduling *resource.PodScheduling + update func(scheduling *resource.PodScheduling) *resource.PodScheduling + wantFailures field.ErrorList + }{ + "valid-no-op-update": { + oldScheduling: validScheduling, + update: func(scheduling *resource.PodScheduling) *resource.PodScheduling { return scheduling }, + }, + "add-claim-status": { + oldScheduling: validScheduling, + update: func(scheduling *resource.PodScheduling) *resource.PodScheduling { + scheduling.Status.ResourceClaims = append(scheduling.Status.ResourceClaims, + resource.ResourceClaimSchedulingStatus{ + Name: "my-claim", + }, + ) + for i := 0; i < resource.PodSchedulingNodeListMaxSize; i++ { + scheduling.Status.ResourceClaims[0].UnsuitableNodes = append( + scheduling.Status.ResourceClaims[0].UnsuitableNodes, + fmt.Sprintf("worker%d", i), + ) + } + return scheduling + }, + }, + "invalid-duplicated-claim-status": { + wantFailures: field.ErrorList{field.Duplicate(field.NewPath("status", "claims").Index(1), "my-claim")}, + oldScheduling: validScheduling, + update: func(scheduling *resource.PodScheduling) *resource.PodScheduling { + for i := 0; i < 2; i++ { + scheduling.Status.ResourceClaims = append(scheduling.Status.ResourceClaims, + resource.ResourceClaimSchedulingStatus{Name: "my-claim"}, + ) + } + return scheduling + }, + }, + "invalid-too-long-claim-status": { + wantFailures: field.ErrorList{field.TooLongMaxLength(field.NewPath("status", "claims").Index(0).Child("unsuitableNodes"), 129, resource.PodSchedulingNodeListMaxSize)}, + oldScheduling: validScheduling, + update: func(scheduling *resource.PodScheduling) *resource.PodScheduling { + scheduling.Status.ResourceClaims = append(scheduling.Status.ResourceClaims, + resource.ResourceClaimSchedulingStatus{ + Name: "my-claim", + }, + ) + for i := 0; i < resource.PodSchedulingNodeListMaxSize+1; i++ { + scheduling.Status.ResourceClaims[0].UnsuitableNodes = append( + scheduling.Status.ResourceClaims[0].UnsuitableNodes, + fmt.Sprintf("worker%d", i), + ) + } + return scheduling + }, + }, + "invalid-node-name": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("status", "claims").Index(0).Child("unsuitableNodes").Index(0), badName, "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")}, + oldScheduling: validScheduling, + update: func(scheduling *resource.PodScheduling) *resource.PodScheduling { + scheduling.Status.ResourceClaims = append(scheduling.Status.ResourceClaims, + resource.ResourceClaimSchedulingStatus{ + Name: "my-claim", + }, + ) + scheduling.Status.ResourceClaims[0].UnsuitableNodes = append( + scheduling.Status.ResourceClaims[0].UnsuitableNodes, + badName, + ) + return scheduling + }, + }, + } + + for name, scenario := range scenarios { + t.Run(name, func(t *testing.T) { + scenario.oldScheduling.ResourceVersion = "1" + errs := ValidatePodSchedulingStatusUpdate(scenario.update(scenario.oldScheduling.DeepCopy()), scenario.oldScheduling) + assert.Equal(t, scenario.wantFailures, errs) + }) + } +} diff --git a/pkg/apis/resource/validation/validation_resourceclaim_test.go b/pkg/apis/resource/validation/validation_resourceclaim_test.go new file mode 100644 index 00000000000..4b3066fe3ca --- /dev/null +++ b/pkg/apis/resource/validation/validation_resourceclaim_test.go @@ -0,0 +1,629 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/utils/pointer" +) + +func testClaim(name, namespace string, spec resource.ResourceClaimSpec) *resource.ResourceClaim { + return &resource.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: spec, + } +} + +func TestValidateClaim(t *testing.T) { + validMode := resource.AllocationModeImmediate + invalidMode := resource.AllocationMode("invalid") + goodName := "foo" + badName := "!@#$%^" + goodNS := "ns" + goodClaimSpec := resource.ResourceClaimSpec{ + ResourceClassName: goodName, + AllocationMode: validMode, + } + now := metav1.Now() + badValue := "spaces not allowed" + + scenarios := map[string]struct { + claim *resource.ResourceClaim + wantFailures field.ErrorList + }{ + "good-claim": { + claim: testClaim(goodName, goodNS, goodClaimSpec), + }, + "missing-name": { + wantFailures: field.ErrorList{field.Required(field.NewPath("metadata", "name"), "name or generateName is required")}, + claim: testClaim("", goodNS, goodClaimSpec), + }, + "bad-name": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("metadata", "name"), badName, "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")}, + claim: testClaim(badName, goodNS, goodClaimSpec), + }, + "missing-namespace": { + wantFailures: field.ErrorList{field.Required(field.NewPath("metadata", "namespace"), "")}, + claim: testClaim(goodName, "", goodClaimSpec), + }, + "generate-name": { + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.GenerateName = "pvc-" + return claim + }(), + }, + "uid": { + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.UID = "ac051fac-2ead-46d9-b8b4-4e0fbeb7455d" + return claim + }(), + }, + "resource-version": { + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.ResourceVersion = "1" + return claim + }(), + }, + "generation": { + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.Generation = 100 + return claim + }(), + }, + "creation-timestamp": { + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.CreationTimestamp = now + return claim + }(), + }, + "deletion-grace-period-seconds": { + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.DeletionGracePeriodSeconds = pointer.Int64(10) + return claim + }(), + }, + "owner-references": { + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.OwnerReferences = []metav1.OwnerReference{ + { + APIVersion: "v1", + Kind: "pod", + Name: "foo", + UID: "ac051fac-2ead-46d9-b8b4-4e0fbeb7455d", + }, + } + return claim + }(), + }, + "finalizers": { + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.Finalizers = []string{ + "example.com/foo", + } + return claim + }(), + }, + "managed-fields": { + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.ManagedFields = []metav1.ManagedFieldsEntry{ + { + FieldsType: "FieldsV1", + Operation: "Apply", + APIVersion: "apps/v1", + Manager: "foo", + }, + } + return claim + }(), + }, + "good-labels": { + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.Labels = map[string]string{ + "apps.kubernetes.io/name": "test", + } + return claim + }(), + }, + "bad-labels": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("metadata", "labels"), badValue, "a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyValue', or 'my_value', or '12345', regex used for validation is '(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?')")}, + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.Labels = map[string]string{ + "hello-world": badValue, + } + return claim + }(), + }, + "good-annotations": { + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.Annotations = map[string]string{ + "foo": "bar", + } + return claim + }(), + }, + "bad-annotations": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("metadata", "annotations"), badName, "name part must consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]')")}, + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.Annotations = map[string]string{ + badName: "hello world", + } + return claim + }(), + }, + "bad-classname": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("spec", "resourceClassName"), badName, "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")}, + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.Spec.ResourceClassName = badName + return claim + }(), + }, + "bad-mode": { + wantFailures: field.ErrorList{field.NotSupported(field.NewPath("spec", "allocationMode"), invalidMode, supportedAllocationModes.List())}, + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.Spec.AllocationMode = invalidMode + return claim + }(), + }, + "good-parameters": { + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.Spec.ParametersRef = &resource.ResourceClaimParametersReference{ + Kind: "foo", + Name: "bar", + } + return claim + }(), + }, + "missing-parameters-kind": { + wantFailures: field.ErrorList{field.Required(field.NewPath("spec", "parametersRef", "kind"), "")}, + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.Spec.ParametersRef = &resource.ResourceClaimParametersReference{ + Name: "bar", + } + return claim + }(), + }, + "missing-parameters-name": { + wantFailures: field.ErrorList{field.Required(field.NewPath("spec", "parametersRef", "name"), "")}, + claim: func() *resource.ResourceClaim { + claim := testClaim(goodName, goodNS, goodClaimSpec) + claim.Spec.ParametersRef = &resource.ResourceClaimParametersReference{ + Kind: "foo", + } + return claim + }(), + }, + } + + for name, scenario := range scenarios { + t.Run(name, func(t *testing.T) { + errs := ValidateClaim(scenario.claim) + assert.Equal(t, scenario.wantFailures, errs) + }) + } +} + +func TestValidateClaimUpdate(t *testing.T) { + name := "valid" + parameters := &resource.ResourceClaimParametersReference{ + Kind: "foo", + Name: "bar", + } + validClaim := testClaim("foo", "ns", resource.ResourceClaimSpec{ + ResourceClassName: name, + AllocationMode: resource.AllocationModeImmediate, + ParametersRef: parameters, + }) + + scenarios := map[string]struct { + oldClaim *resource.ResourceClaim + update func(claim *resource.ResourceClaim) *resource.ResourceClaim + wantFailures field.ErrorList + }{ + "valid-no-op-update": { + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { return claim }, + }, + "invalid-update-class": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("spec"), func() resource.ResourceClaimSpec { + spec := validClaim.Spec.DeepCopy() + spec.ResourceClassName += "2" + return *spec + }(), "field is immutable")}, + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Spec.ResourceClassName += "2" + return claim + }, + }, + "invalid-update-remove-parameters": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("spec"), func() resource.ResourceClaimSpec { + spec := validClaim.Spec.DeepCopy() + spec.ParametersRef = nil + return *spec + }(), "field is immutable")}, + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Spec.ParametersRef = nil + return claim + }, + }, + "invalid-update-mode": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("spec"), func() resource.ResourceClaimSpec { + spec := validClaim.Spec.DeepCopy() + spec.AllocationMode = resource.AllocationModeWaitForFirstConsumer + return *spec + }(), "field is immutable")}, + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Spec.AllocationMode = resource.AllocationModeWaitForFirstConsumer + return claim + }, + }, + } + + for name, scenario := range scenarios { + t.Run(name, func(t *testing.T) { + scenario.oldClaim.ResourceVersion = "1" + errs := ValidateClaimUpdate(scenario.update(scenario.oldClaim.DeepCopy()), scenario.oldClaim) + assert.Equal(t, scenario.wantFailures, errs) + }) + } +} + +func TestValidateClaimStatusUpdate(t *testing.T) { + validClaim := testClaim("foo", "ns", resource.ResourceClaimSpec{ + ResourceClassName: "valid", + AllocationMode: resource.AllocationModeImmediate, + }) + + validAllocatedClaim := validClaim.DeepCopy() + validAllocatedClaim.Status = resource.ResourceClaimStatus{ + DriverName: "valid", + Allocation: &resource.AllocationResult{ + ResourceHandle: strings.Repeat(" ", resource.ResourceHandleMaxSize), + Shareable: true, + }, + } + + scenarios := map[string]struct { + oldClaim *resource.ResourceClaim + update func(claim *resource.ResourceClaim) *resource.ResourceClaim + wantFailures field.ErrorList + }{ + "valid-no-op-update": { + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { return claim }, + }, + "add-driver": { + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.DriverName = "valid" + return claim + }, + }, + "invalid-add-allocation": { + wantFailures: field.ErrorList{field.Required(field.NewPath("status", "driverName"), "must be specified when `allocation` is set")}, + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + // DriverName must also get set here! + claim.Status.Allocation = &resource.AllocationResult{} + return claim + }, + }, + "valid-add-allocation": { + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.DriverName = "valid" + claim.Status.Allocation = &resource.AllocationResult{ + ResourceHandle: strings.Repeat(" ", resource.ResourceHandleMaxSize), + } + return claim + }, + }, + "invalid-allocation-handle": { + wantFailures: field.ErrorList{field.TooLongMaxLength(field.NewPath("status", "allocation", "resourceHandle"), resource.ResourceHandleMaxSize+1, resource.ResourceHandleMaxSize)}, + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.DriverName = "valid" + claim.Status.Allocation = &resource.AllocationResult{ + ResourceHandle: strings.Repeat(" ", resource.ResourceHandleMaxSize+1), + } + return claim + }, + }, + "invalid-node-selector": { + wantFailures: field.ErrorList{field.Required(field.NewPath("status", "allocation", "availableOnNodes", "nodeSelectorTerms"), "must have at least one node selector term")}, + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.DriverName = "valid" + claim.Status.Allocation = &resource.AllocationResult{ + AvailableOnNodes: &core.NodeSelector{ + // Must not be empty. + }, + } + return claim + }, + }, + "add-reservation": { + oldClaim: validAllocatedClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + for i := 0; i < resource.ResourceClaimReservedForMaxSize; i++ { + claim.Status.ReservedFor = append(claim.Status.ReservedFor, + resource.ResourceClaimConsumerReference{ + Resource: "pods", + Name: fmt.Sprintf("foo-%d", i), + UID: "1", + }) + } + return claim + }, + }, + "add-reservation-and-allocation": { + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status = *validAllocatedClaim.Status.DeepCopy() + for i := 0; i < resource.ResourceClaimReservedForMaxSize; i++ { + claim.Status.ReservedFor = append(claim.Status.ReservedFor, + resource.ResourceClaimConsumerReference{ + Resource: "pods", + Name: fmt.Sprintf("foo-%d", i), + UID: "1", + }) + } + return claim + }, + }, + "invalid-reserved-for-too-large": { + wantFailures: field.ErrorList{field.TooLongMaxLength(field.NewPath("status", "reservedFor"), resource.ResourceClaimReservedForMaxSize+1, resource.ResourceClaimReservedForMaxSize)}, + oldClaim: validAllocatedClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + for i := 0; i < resource.ResourceClaimReservedForMaxSize+1; i++ { + claim.Status.ReservedFor = append(claim.Status.ReservedFor, + resource.ResourceClaimConsumerReference{ + Resource: "pods", + Name: fmt.Sprintf("foo-%d", i), + UID: "1", + }) + } + return claim + }, + }, + "invalid-reserved-for-duplicate": { + wantFailures: field.ErrorList{field.Duplicate(field.NewPath("status", "reservedFor").Index(1), resource.ResourceClaimConsumerReference{ + Resource: "pods", + Name: "foo", + UID: "1", + })}, + oldClaim: validAllocatedClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + for i := 0; i < 2; i++ { + claim.Status.ReservedFor = append(claim.Status.ReservedFor, + resource.ResourceClaimConsumerReference{ + Resource: "pods", + Name: "foo", + UID: "1", + }) + } + return claim + }, + }, + "invalid-reserved-for-not-shared": { + wantFailures: field.ErrorList{field.Forbidden(field.NewPath("status", "reservedFor"), "may not be reserved more than once")}, + oldClaim: func() *resource.ResourceClaim { + claim := validAllocatedClaim.DeepCopy() + claim.Status.Allocation.Shareable = false + return claim + }(), + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + for i := 0; i < 2; i++ { + claim.Status.ReservedFor = append(claim.Status.ReservedFor, + resource.ResourceClaimConsumerReference{ + Resource: "pods", + Name: fmt.Sprintf("foo-%d", i), + UID: "1", + }) + } + return claim + }, + }, + "invalid-reserved-for-no-allocation": { + wantFailures: field.ErrorList{field.Forbidden(field.NewPath("status", "reservedFor"), "may not be specified when `allocated` is not set")}, + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.DriverName = "valid" + claim.Status.ReservedFor = []resource.ResourceClaimConsumerReference{ + { + Resource: "pods", + Name: "foo", + UID: "1", + }, + } + return claim + }, + }, + "invalid-reserved-for-no-resource": { + wantFailures: field.ErrorList{field.Required(field.NewPath("status", "reservedFor").Index(0).Child("resource"), "")}, + oldClaim: validAllocatedClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.ReservedFor = []resource.ResourceClaimConsumerReference{ + { + Name: "foo", + UID: "1", + }, + } + return claim + }, + }, + "invalid-reserved-for-no-name": { + wantFailures: field.ErrorList{field.Required(field.NewPath("status", "reservedFor").Index(0).Child("name"), "")}, + oldClaim: validAllocatedClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.ReservedFor = []resource.ResourceClaimConsumerReference{ + { + Resource: "pods", + UID: "1", + }, + } + return claim + }, + }, + "invalid-reserved-for-no-uid": { + wantFailures: field.ErrorList{field.Required(field.NewPath("status", "reservedFor").Index(0).Child("uid"), "")}, + oldClaim: validAllocatedClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.ReservedFor = []resource.ResourceClaimConsumerReference{ + { + Resource: "pods", + Name: "foo", + }, + } + return claim + }, + }, + "invalid-reserved-deleted": { + wantFailures: field.ErrorList{field.Forbidden(field.NewPath("status", "reservedFor"), "new entries may not be added while `deallocationRequested` or `deletionTimestamp` are set")}, + oldClaim: func() *resource.ResourceClaim { + claim := validAllocatedClaim.DeepCopy() + var deletionTimestamp metav1.Time + claim.DeletionTimestamp = &deletionTimestamp + return claim + }(), + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.ReservedFor = []resource.ResourceClaimConsumerReference{ + { + Resource: "pods", + Name: "foo", + UID: "1", + }, + } + return claim + }, + }, + "invalid-reserved-deallocation-requested": { + wantFailures: field.ErrorList{field.Forbidden(field.NewPath("status", "reservedFor"), "new entries may not be added while `deallocationRequested` or `deletionTimestamp` are set")}, + oldClaim: func() *resource.ResourceClaim { + claim := validAllocatedClaim.DeepCopy() + claim.Status.DeallocationRequested = true + return claim + }(), + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.ReservedFor = []resource.ResourceClaimConsumerReference{ + { + Resource: "pods", + Name: "foo", + UID: "1", + }, + } + return claim + }, + }, + "add-deallocation-requested": { + oldClaim: validAllocatedClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.DeallocationRequested = true + return claim + }, + }, + "invalid-deallocation-requested-removal": { + wantFailures: field.ErrorList{field.Forbidden(field.NewPath("status", "deallocationRequested"), "may not be cleared when `allocation` is set")}, + oldClaim: func() *resource.ResourceClaim { + claim := validAllocatedClaim.DeepCopy() + claim.Status.DeallocationRequested = true + return claim + }(), + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.DeallocationRequested = false + return claim + }, + }, + "invalid-deallocation-requested-in-use": { + wantFailures: field.ErrorList{field.Forbidden(field.NewPath("status", "deallocationRequested"), "deallocation cannot be requested while `reservedFor` is set")}, + oldClaim: func() *resource.ResourceClaim { + claim := validAllocatedClaim.DeepCopy() + claim.Status.ReservedFor = []resource.ResourceClaimConsumerReference{ + { + Resource: "pods", + Name: "foo", + UID: "1", + }, + } + return claim + }(), + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.DeallocationRequested = true + return claim + }, + }, + "invalid-deallocation-not-allocated": { + wantFailures: field.ErrorList{field.Forbidden(field.NewPath("status"), "`allocation` must be set when `deallocationRequested` is set")}, + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.DeallocationRequested = true + return claim + }, + }, + "invalid-allocation-removal-not-reset": { + wantFailures: field.ErrorList{field.Forbidden(field.NewPath("status"), "`allocation` must be set when `deallocationRequested` is set")}, + oldClaim: func() *resource.ResourceClaim { + claim := validAllocatedClaim.DeepCopy() + claim.Status.DeallocationRequested = true + return claim + }(), + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.Allocation = nil + return claim + }, + }, + } + + for name, scenario := range scenarios { + t.Run(name, func(t *testing.T) { + scenario.oldClaim.ResourceVersion = "1" + errs := ValidateClaimStatusUpdate(scenario.update(scenario.oldClaim.DeepCopy()), scenario.oldClaim) + assert.Equal(t, scenario.wantFailures, errs) + }) + } +} diff --git a/pkg/apis/resource/validation/validation_resourceclaimtemplate_test.go b/pkg/apis/resource/validation/validation_resourceclaimtemplate_test.go new file mode 100644 index 00000000000..23263f36114 --- /dev/null +++ b/pkg/apis/resource/validation/validation_resourceclaimtemplate_test.go @@ -0,0 +1,313 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/utils/pointer" +) + +func testClaimTemplate(name, namespace string, spec resource.ResourceClaimSpec) *resource.ResourceClaimTemplate { + return &resource.ResourceClaimTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: resource.ResourceClaimTemplateSpec{ + Spec: spec, + }, + } +} + +func TestValidateClaimTemplate(t *testing.T) { + validMode := resource.AllocationModeImmediate + invalidMode := resource.AllocationMode("invalid") + goodName := "foo" + badName := "!@#$%^" + goodNS := "ns" + goodClaimSpec := resource.ResourceClaimSpec{ + ResourceClassName: goodName, + AllocationMode: validMode, + } + now := metav1.Now() + badValue := "spaces not allowed" + + scenarios := map[string]struct { + template *resource.ResourceClaimTemplate + wantFailures field.ErrorList + }{ + "good-claim": { + template: testClaimTemplate(goodName, goodNS, goodClaimSpec), + }, + "missing-name": { + wantFailures: field.ErrorList{field.Required(field.NewPath("metadata", "name"), "name or generateName is required")}, + template: testClaimTemplate("", goodNS, goodClaimSpec), + }, + "bad-name": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("metadata", "name"), badName, "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")}, + template: testClaimTemplate(badName, goodNS, goodClaimSpec), + }, + "missing-namespace": { + wantFailures: field.ErrorList{field.Required(field.NewPath("metadata", "namespace"), "")}, + template: testClaimTemplate(goodName, "", goodClaimSpec), + }, + "generate-name": { + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.GenerateName = "pvc-" + return template + }(), + }, + "uid": { + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.UID = "ac051fac-2ead-46d9-b8b4-4e0fbeb7455d" + return template + }(), + }, + "resource-version": { + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.ResourceVersion = "1" + return template + }(), + }, + "generation": { + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.Generation = 100 + return template + }(), + }, + "creation-timestamp": { + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.CreationTimestamp = now + return template + }(), + }, + "deletion-grace-period-seconds": { + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.DeletionGracePeriodSeconds = pointer.Int64(10) + return template + }(), + }, + "owner-references": { + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.OwnerReferences = []metav1.OwnerReference{ + { + APIVersion: "v1", + Kind: "pod", + Name: "foo", + UID: "ac051fac-2ead-46d9-b8b4-4e0fbeb7455d", + }, + } + return template + }(), + }, + "finalizers": { + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.Finalizers = []string{ + "example.com/foo", + } + return template + }(), + }, + "managed-fields": { + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.ManagedFields = []metav1.ManagedFieldsEntry{ + { + FieldsType: "FieldsV1", + Operation: "Apply", + APIVersion: "apps/v1", + Manager: "foo", + }, + } + return template + }(), + }, + "good-labels": { + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.Labels = map[string]string{ + "apps.kubernetes.io/name": "test", + } + return template + }(), + }, + "bad-labels": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("metadata", "labels"), badValue, "a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyValue', or 'my_value', or '12345', regex used for validation is '(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?')")}, + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.Labels = map[string]string{ + "hello-world": badValue, + } + return template + }(), + }, + "good-annotations": { + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.Annotations = map[string]string{ + "foo": "bar", + } + return template + }(), + }, + "bad-annotations": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("metadata", "annotations"), badName, "name part must consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]')")}, + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.Annotations = map[string]string{ + badName: "hello world", + } + return template + }(), + }, + "bad-classname": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("spec", "spec", "resourceClassName"), badName, "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")}, + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.Spec.Spec.ResourceClassName = badName + return template + }(), + }, + "bad-mode": { + wantFailures: field.ErrorList{field.NotSupported(field.NewPath("spec", "spec", "allocationMode"), invalidMode, supportedAllocationModes.List())}, + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.Spec.Spec.AllocationMode = invalidMode + return template + }(), + }, + "good-parameters": { + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.Spec.Spec.ParametersRef = &resource.ResourceClaimParametersReference{ + Kind: "foo", + Name: "bar", + } + return template + }(), + }, + "missing-parameters-kind": { + wantFailures: field.ErrorList{field.Required(field.NewPath("spec", "spec", "parametersRef", "kind"), "")}, + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.Spec.Spec.ParametersRef = &resource.ResourceClaimParametersReference{ + Name: "bar", + } + return template + }(), + }, + "missing-parameters-name": { + wantFailures: field.ErrorList{field.Required(field.NewPath("spec", "spec", "parametersRef", "name"), "")}, + template: func() *resource.ResourceClaimTemplate { + template := testClaimTemplate(goodName, goodNS, goodClaimSpec) + template.Spec.Spec.ParametersRef = &resource.ResourceClaimParametersReference{ + Kind: "foo", + } + return template + }(), + }, + } + + for name, scenario := range scenarios { + t.Run(name, func(t *testing.T) { + errs := ValidateClaimTemplate(scenario.template) + assert.Equal(t, scenario.wantFailures, errs) + }) + } +} + +func TestValidateClaimTemplateUpdate(t *testing.T) { + name := "valid" + parameters := &resource.ResourceClaimParametersReference{ + Kind: "foo", + Name: "bar", + } + validClaimTemplate := testClaimTemplate("foo", "ns", resource.ResourceClaimSpec{ + ResourceClassName: name, + AllocationMode: resource.AllocationModeImmediate, + ParametersRef: parameters, + }) + + scenarios := map[string]struct { + oldClaimTemplate *resource.ResourceClaimTemplate + update func(claim *resource.ResourceClaimTemplate) *resource.ResourceClaimTemplate + wantFailures field.ErrorList + }{ + "valid-no-op-update": { + oldClaimTemplate: validClaimTemplate, + update: func(claim *resource.ResourceClaimTemplate) *resource.ResourceClaimTemplate { return claim }, + }, + "invalid-update-class": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("spec"), func() resource.ResourceClaimTemplateSpec { + spec := validClaimTemplate.Spec.DeepCopy() + spec.Spec.ResourceClassName += "2" + return *spec + }(), "field is immutable")}, + oldClaimTemplate: validClaimTemplate, + update: func(template *resource.ResourceClaimTemplate) *resource.ResourceClaimTemplate { + template.Spec.Spec.ResourceClassName += "2" + return template + }, + }, + "invalid-update-remove-parameters": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("spec"), func() resource.ResourceClaimTemplateSpec { + spec := validClaimTemplate.Spec.DeepCopy() + spec.Spec.ParametersRef = nil + return *spec + }(), "field is immutable")}, + oldClaimTemplate: validClaimTemplate, + update: func(template *resource.ResourceClaimTemplate) *resource.ResourceClaimTemplate { + template.Spec.Spec.ParametersRef = nil + return template + }, + }, + "invalid-update-mode": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("spec"), func() resource.ResourceClaimTemplateSpec { + spec := validClaimTemplate.Spec.DeepCopy() + spec.Spec.AllocationMode = resource.AllocationModeWaitForFirstConsumer + return *spec + }(), "field is immutable")}, + oldClaimTemplate: validClaimTemplate, + update: func(template *resource.ResourceClaimTemplate) *resource.ResourceClaimTemplate { + template.Spec.Spec.AllocationMode = resource.AllocationModeWaitForFirstConsumer + return template + }, + }, + } + + for name, scenario := range scenarios { + t.Run(name, func(t *testing.T) { + scenario.oldClaimTemplate.ResourceVersion = "1" + errs := ValidateClaimTemplateUpdate(scenario.update(scenario.oldClaimTemplate.DeepCopy()), scenario.oldClaimTemplate) + assert.Equal(t, scenario.wantFailures, errs) + }) + } +} diff --git a/pkg/apis/resource/validation/validation_resourceclass_test.go b/pkg/apis/resource/validation/validation_resourceclass_test.go new file mode 100644 index 00000000000..c84429f9406 --- /dev/null +++ b/pkg/apis/resource/validation/validation_resourceclass_test.go @@ -0,0 +1,282 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/utils/pointer" +) + +func testClass(name, driverName string) *resource.ResourceClass { + return &resource.ResourceClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + DriverName: driverName, + } +} + +func TestValidateClass(t *testing.T) { + goodName := "foo" + now := metav1.Now() + goodParameters := resource.ResourceClassParametersReference{ + Name: "valid", + Namespace: "valid", + Kind: "foo", + } + badName := "!@#$%^" + badValue := "spaces not allowed" + + scenarios := map[string]struct { + class *resource.ResourceClass + wantFailures field.ErrorList + }{ + "good-class": { + class: testClass(goodName, goodName), + }, + "good-long-driver-name": { + class: testClass(goodName, "acme.example.com"), + }, + "missing-name": { + wantFailures: field.ErrorList{field.Required(field.NewPath("metadata", "name"), "name or generateName is required")}, + class: testClass("", goodName), + }, + "bad-name": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("metadata", "name"), badName, "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")}, + class: testClass(badName, goodName), + }, + "generate-name": { + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.GenerateName = "pvc-" + return class + }(), + }, + "uid": { + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.UID = "ac051fac-2ead-46d9-b8b4-4e0fbeb7455d" + return class + }(), + }, + "resource-version": { + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.ResourceVersion = "1" + return class + }(), + }, + "generation": { + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.Generation = 100 + return class + }(), + }, + "creation-timestamp": { + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.CreationTimestamp = now + return class + }(), + }, + "deletion-grace-period-seconds": { + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.DeletionGracePeriodSeconds = pointer.Int64(10) + return class + }(), + }, + "owner-references": { + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.OwnerReferences = []metav1.OwnerReference{ + { + APIVersion: "v1", + Kind: "pod", + Name: "foo", + UID: "ac051fac-2ead-46d9-b8b4-4e0fbeb7455d", + }, + } + return class + }(), + }, + "finalizers": { + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.Finalizers = []string{ + "example.com/foo", + } + return class + }(), + }, + "managed-fields": { + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.ManagedFields = []metav1.ManagedFieldsEntry{ + { + FieldsType: "FieldsV1", + Operation: "Apply", + APIVersion: "apps/v1", + Manager: "foo", + }, + } + return class + }(), + }, + "good-labels": { + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.Labels = map[string]string{ + "apps.kubernetes.io/name": "test", + } + return class + }(), + }, + "bad-labels": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("metadata", "labels"), badValue, "a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyValue', or 'my_value', or '12345', regex used for validation is '(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?')")}, + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.Labels = map[string]string{ + "hello-world": badValue, + } + return class + }(), + }, + "good-annotations": { + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.Annotations = map[string]string{ + "foo": "bar", + } + return class + }(), + }, + "bad-annotations": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("metadata", "annotations"), badName, "name part must consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]')")}, + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.Annotations = map[string]string{ + badName: "hello world", + } + return class + }(), + }, + "missing-driver-name": { + wantFailures: field.ErrorList{field.Required(field.NewPath("driverName"), ""), + field.Invalid(field.NewPath("driverName"), "", "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')"), + }, + class: testClass(goodName, ""), + }, + "invalid-driver-name": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("driverName"), badName, "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")}, + class: testClass(goodName, badName), + }, + "invalid-qualified-driver-name": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("driverName"), goodName+"/path", "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")}, + class: testClass(goodName, goodName+"/path"), + }, + "good-parameters": { + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.ParametersRef = goodParameters.DeepCopy() + return class + }(), + }, + "missing-parameters-name": { + wantFailures: field.ErrorList{field.Required(field.NewPath("parametersRef", "name"), "")}, + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.ParametersRef = goodParameters.DeepCopy() + class.ParametersRef.Name = "" + return class + }(), + }, + "bad-parameters-namespace": { + wantFailures: field.ErrorList{field.Invalid(field.NewPath("parametersRef", "namespace"), badName, "a lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?')")}, + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.ParametersRef = goodParameters.DeepCopy() + class.ParametersRef.Namespace = badName + return class + }(), + }, + "missing-parameters-kind": { + wantFailures: field.ErrorList{field.Required(field.NewPath("parametersRef", "kind"), "")}, + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.ParametersRef = goodParameters.DeepCopy() + class.ParametersRef.Kind = "" + return class + }(), + }, + "invalid-node-selector": { + wantFailures: field.ErrorList{field.Required(field.NewPath("suitableNodes", "nodeSelectorTerms"), "must have at least one node selector term")}, + class: func() *resource.ResourceClass { + class := testClass(goodName, goodName) + class.SuitableNodes = &core.NodeSelector{ + // Must not be empty. + } + return class + }(), + }, + } + + for name, scenario := range scenarios { + t.Run(name, func(t *testing.T) { + errs := ValidateClass(scenario.class) + assert.Equal(t, scenario.wantFailures, errs) + }) + } +} + +func TestValidateClassUpdate(t *testing.T) { + validClass := testClass("foo", "valid") + + scenarios := map[string]struct { + oldClass *resource.ResourceClass + update func(class *resource.ResourceClass) *resource.ResourceClass + wantFailures field.ErrorList + }{ + "valid-no-op-update": { + oldClass: validClass, + update: func(class *resource.ResourceClass) *resource.ResourceClass { return class }, + }, + "update-driver": { + oldClass: validClass, + update: func(class *resource.ResourceClass) *resource.ResourceClass { + class.DriverName += "2" + return class + }, + }, + } + + for name, scenario := range scenarios { + t.Run(name, func(t *testing.T) { + scenario.oldClass.ResourceVersion = "1" + errs := ValidateClassUpdate(scenario.update(scenario.oldClass.DeepCopy()), scenario.oldClass) + assert.Equal(t, scenario.wantFailures, errs) + }) + } +} diff --git a/pkg/apis/resource/zz_generated.deepcopy.go b/pkg/apis/resource/zz_generated.deepcopy.go new file mode 100644 index 00000000000..d5810b3b5e6 --- /dev/null +++ b/pkg/apis/resource/zz_generated.deepcopy.go @@ -0,0 +1,477 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package resource + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + core "k8s.io/kubernetes/pkg/apis/core" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AllocationResult) DeepCopyInto(out *AllocationResult) { + *out = *in + if in.AvailableOnNodes != nil { + in, out := &in.AvailableOnNodes, &out.AvailableOnNodes + *out = new(core.NodeSelector) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllocationResult. +func (in *AllocationResult) DeepCopy() *AllocationResult { + if in == nil { + return nil + } + out := new(AllocationResult) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodScheduling) DeepCopyInto(out *PodScheduling) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodScheduling. +func (in *PodScheduling) DeepCopy() *PodScheduling { + if in == nil { + return nil + } + out := new(PodScheduling) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PodScheduling) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodSchedulingList) DeepCopyInto(out *PodSchedulingList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]PodScheduling, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSchedulingList. +func (in *PodSchedulingList) DeepCopy() *PodSchedulingList { + if in == nil { + return nil + } + out := new(PodSchedulingList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PodSchedulingList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodSchedulingSpec) DeepCopyInto(out *PodSchedulingSpec) { + *out = *in + if in.PotentialNodes != nil { + in, out := &in.PotentialNodes, &out.PotentialNodes + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSchedulingSpec. +func (in *PodSchedulingSpec) DeepCopy() *PodSchedulingSpec { + if in == nil { + return nil + } + out := new(PodSchedulingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodSchedulingStatus) DeepCopyInto(out *PodSchedulingStatus) { + *out = *in + if in.ResourceClaims != nil { + in, out := &in.ResourceClaims, &out.ResourceClaims + *out = make([]ResourceClaimSchedulingStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSchedulingStatus. +func (in *PodSchedulingStatus) DeepCopy() *PodSchedulingStatus { + if in == nil { + return nil + } + out := new(PodSchedulingStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaim) DeepCopyInto(out *ResourceClaim) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaim. +func (in *ResourceClaim) DeepCopy() *ResourceClaim { + if in == nil { + return nil + } + out := new(ResourceClaim) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ResourceClaim) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimConsumerReference) DeepCopyInto(out *ResourceClaimConsumerReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimConsumerReference. +func (in *ResourceClaimConsumerReference) DeepCopy() *ResourceClaimConsumerReference { + if in == nil { + return nil + } + out := new(ResourceClaimConsumerReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimList) DeepCopyInto(out *ResourceClaimList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ResourceClaim, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimList. +func (in *ResourceClaimList) DeepCopy() *ResourceClaimList { + if in == nil { + return nil + } + out := new(ResourceClaimList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ResourceClaimList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimParametersReference) DeepCopyInto(out *ResourceClaimParametersReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimParametersReference. +func (in *ResourceClaimParametersReference) DeepCopy() *ResourceClaimParametersReference { + if in == nil { + return nil + } + out := new(ResourceClaimParametersReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimSchedulingStatus) DeepCopyInto(out *ResourceClaimSchedulingStatus) { + *out = *in + if in.UnsuitableNodes != nil { + in, out := &in.UnsuitableNodes, &out.UnsuitableNodes + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimSchedulingStatus. +func (in *ResourceClaimSchedulingStatus) DeepCopy() *ResourceClaimSchedulingStatus { + if in == nil { + return nil + } + out := new(ResourceClaimSchedulingStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimSpec) DeepCopyInto(out *ResourceClaimSpec) { + *out = *in + if in.ParametersRef != nil { + in, out := &in.ParametersRef, &out.ParametersRef + *out = new(ResourceClaimParametersReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimSpec. +func (in *ResourceClaimSpec) DeepCopy() *ResourceClaimSpec { + if in == nil { + return nil + } + out := new(ResourceClaimSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimStatus) DeepCopyInto(out *ResourceClaimStatus) { + *out = *in + if in.Allocation != nil { + in, out := &in.Allocation, &out.Allocation + *out = new(AllocationResult) + (*in).DeepCopyInto(*out) + } + if in.ReservedFor != nil { + in, out := &in.ReservedFor, &out.ReservedFor + *out = make([]ResourceClaimConsumerReference, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimStatus. +func (in *ResourceClaimStatus) DeepCopy() *ResourceClaimStatus { + if in == nil { + return nil + } + out := new(ResourceClaimStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimTemplate) DeepCopyInto(out *ResourceClaimTemplate) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimTemplate. +func (in *ResourceClaimTemplate) DeepCopy() *ResourceClaimTemplate { + if in == nil { + return nil + } + out := new(ResourceClaimTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ResourceClaimTemplate) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimTemplateList) DeepCopyInto(out *ResourceClaimTemplateList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ResourceClaimTemplate, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimTemplateList. +func (in *ResourceClaimTemplateList) DeepCopy() *ResourceClaimTemplateList { + if in == nil { + return nil + } + out := new(ResourceClaimTemplateList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ResourceClaimTemplateList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimTemplateSpec) DeepCopyInto(out *ResourceClaimTemplateSpec) { + *out = *in + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimTemplateSpec. +func (in *ResourceClaimTemplateSpec) DeepCopy() *ResourceClaimTemplateSpec { + if in == nil { + return nil + } + out := new(ResourceClaimTemplateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClass) DeepCopyInto(out *ResourceClass) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.ParametersRef != nil { + in, out := &in.ParametersRef, &out.ParametersRef + *out = new(ResourceClassParametersReference) + **out = **in + } + if in.SuitableNodes != nil { + in, out := &in.SuitableNodes, &out.SuitableNodes + *out = new(core.NodeSelector) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClass. +func (in *ResourceClass) DeepCopy() *ResourceClass { + if in == nil { + return nil + } + out := new(ResourceClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ResourceClass) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClassList) DeepCopyInto(out *ResourceClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ResourceClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClassList. +func (in *ResourceClassList) DeepCopy() *ResourceClassList { + if in == nil { + return nil + } + out := new(ResourceClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ResourceClassList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClassParametersReference) DeepCopyInto(out *ResourceClassParametersReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClassParametersReference. +func (in *ResourceClassParametersReference) DeepCopy() *ResourceClassParametersReference { + if in == nil { + return nil + } + out := new(ResourceClassParametersReference) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/controller/resourceclaim/OWNERS b/pkg/controller/resourceclaim/OWNERS new file mode 100644 index 00000000000..8a274491d48 --- /dev/null +++ b/pkg/controller/resourceclaim/OWNERS @@ -0,0 +1,12 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - sig-node-approvers + - klueska + - pohly +reviewers: + - klueska + - pohly + - bart0sh +labels: + - sig/node diff --git a/pkg/controller/resourceclaim/controller.go b/pkg/controller/resourceclaim/controller.go new file mode 100644 index 00000000000..6a484b90037 --- /dev/null +++ b/pkg/controller/resourceclaim/controller.go @@ -0,0 +1,479 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourceclaim + +import ( + "context" + "fmt" + "strings" + "time" + + v1 "k8s.io/api/core/v1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + v1informers "k8s.io/client-go/informers/core/v1" + resourcev1alpha1informers "k8s.io/client-go/informers/resource/v1alpha1" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + v1core "k8s.io/client-go/kubernetes/typed/core/v1" + v1listers "k8s.io/client-go/listers/core/v1" + resourcev1alpha1listers "k8s.io/client-go/listers/resource/v1alpha1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/workqueue" + "k8s.io/dynamic-resource-allocation/resourceclaim" + "k8s.io/klog/v2" + podutil "k8s.io/kubernetes/pkg/api/v1/pod" + "k8s.io/kubernetes/pkg/controller/resourceclaim/metrics" +) + +const ( + // podResourceClaimIndex is the lookup name for the index function which indexes by pod ResourceClaim templates. + podResourceClaimIndex = "pod-resource-claim-index" + + maxUIDCacheEntries = 500 +) + +// Controller creates ResourceClaims for ResourceClaimTemplates in a pod spec. +type Controller struct { + // kubeClient is the kube API client used to communicate with the API + // server. + kubeClient clientset.Interface + + // claimLister is the shared ResourceClaim lister used to fetch and store ResourceClaim + // objects from the API server. It is shared with other controllers and + // therefore the ResourceClaim objects in its store should be treated as immutable. + claimLister resourcev1alpha1listers.ResourceClaimLister + claimsSynced cache.InformerSynced + + // podLister is the shared Pod lister used to fetch Pod + // objects from the API server. It is shared with other controllers and + // therefore the Pod objects in its store should be treated as immutable. + podLister v1listers.PodLister + podSynced cache.InformerSynced + + // templateLister is the shared ResourceClaimTemplate lister used to + // fetch template objects from the API server. It is shared with other + // controllers and therefore the objects in its store should be treated + // as immutable. + templateLister resourcev1alpha1listers.ResourceClaimTemplateLister + templatesSynced cache.InformerSynced + + // podIndexer has the common PodResourceClaim indexer indexer installed To + // limit iteration over pods to those of interest. + podIndexer cache.Indexer + + // recorder is used to record events in the API server + recorder record.EventRecorder + + queue workqueue.RateLimitingInterface + + // The deletedObjects cache keeps track of Pods for which we know that + // they have existed and have been removed. For those we can be sure + // that a ReservedFor entry needs to be removed. + deletedObjects *uidCache +} + +const ( + claimKeyPrefix = "claim:" + podKeyPrefix = "pod:" +) + +// NewController creates a ResourceClaim controller. +func NewController( + kubeClient clientset.Interface, + podInformer v1informers.PodInformer, + claimInformer resourcev1alpha1informers.ResourceClaimInformer, + templateInformer resourcev1alpha1informers.ResourceClaimTemplateInformer) (*Controller, error) { + + ec := &Controller{ + kubeClient: kubeClient, + podLister: podInformer.Lister(), + podIndexer: podInformer.Informer().GetIndexer(), + podSynced: podInformer.Informer().HasSynced, + claimLister: claimInformer.Lister(), + claimsSynced: claimInformer.Informer().HasSynced, + templateLister: templateInformer.Lister(), + templatesSynced: templateInformer.Informer().HasSynced, + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "resource_claim"), + deletedObjects: newUIDCache(maxUIDCacheEntries), + } + + metrics.RegisterMetrics() + + eventBroadcaster := record.NewBroadcaster() + eventBroadcaster.StartLogging(klog.Infof) + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) + ec.recorder = eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "resource_claim"}) + + if _, err := podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + ec.enqueuePod(obj, false) + }, + UpdateFunc: func(old, updated interface{}) { + ec.enqueuePod(updated, false) + }, + DeleteFunc: func(obj interface{}) { + ec.enqueuePod(obj, true) + }, + }); err != nil { + return nil, err + } + if _, err := claimInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: ec.onResourceClaimAddOrUpdate, + UpdateFunc: func(old, updated interface{}) { + ec.onResourceClaimAddOrUpdate(updated) + }, + DeleteFunc: ec.onResourceClaimDelete, + }); err != nil { + return nil, err + } + if err := ec.podIndexer.AddIndexers(cache.Indexers{podResourceClaimIndex: podResourceClaimIndexFunc}); err != nil { + return nil, fmt.Errorf("could not initialize ResourceClaim controller: %w", err) + } + + return ec, nil +} + +func (ec *Controller) enqueuePod(obj interface{}, deleted bool) { + if d, ok := obj.(cache.DeletedFinalStateUnknown); ok { + obj = d.Obj + } + pod, ok := obj.(*v1.Pod) + if !ok { + // Not a pod?! + return + } + + if deleted { + ec.deletedObjects.Add(pod.UID) + } + + if len(pod.Spec.ResourceClaims) == 0 { + // Nothing to do for it at all. + return + } + + // Release reservations of a deleted or completed pod? + if deleted || + podutil.IsPodTerminal(pod) || + // Deleted and not scheduled: + pod.DeletionTimestamp != nil && pod.Spec.NodeName == "" { + for _, podClaim := range pod.Spec.ResourceClaims { + claimName := resourceclaim.Name(pod, &podClaim) + ec.queue.Add(claimKeyPrefix + pod.Namespace + "/" + claimName) + } + } + + // Create ResourceClaim for inline templates? + if pod.DeletionTimestamp == nil { + for _, podClaim := range pod.Spec.ResourceClaims { + if podClaim.Source.ResourceClaimTemplateName != nil { + // It has at least one inline template, work on it. + ec.queue.Add(podKeyPrefix + pod.Namespace + "/" + pod.Name) + break + } + } + } +} + +func (ec *Controller) onResourceClaimAddOrUpdate(obj interface{}) { + claim, ok := obj.(*resourcev1alpha1.ResourceClaim) + if !ok { + return + } + + // When starting up, we have to check all claims to find those with + // stale pods in ReservedFor. During an update, a pod might get added + // that already no longer exists. + ec.queue.Add(claimKeyPrefix + claim.Namespace + "/" + claim.Name) +} + +func (ec *Controller) onResourceClaimDelete(obj interface{}) { + claim, ok := obj.(*resourcev1alpha1.ResourceClaim) + if !ok { + return + } + + // Someone deleted a ResourceClaim, either intentionally or + // accidentally. If there is a pod referencing it because of + // an inline resource, then we should re-create the ResourceClaim. + // The common indexer does some prefiltering for us by + // limiting the list to those pods which reference + // the ResourceClaim. + objs, err := ec.podIndexer.ByIndex(podResourceClaimIndex, fmt.Sprintf("%s/%s", claim.Namespace, claim.Name)) + if err != nil { + runtime.HandleError(fmt.Errorf("listing pods from cache: %v", err)) + return + } + for _, obj := range objs { + ec.enqueuePod(obj, false) + } +} + +func (ec *Controller) Run(ctx context.Context, workers int) { + defer runtime.HandleCrash() + defer ec.queue.ShutDown() + + klog.Infof("Starting ephemeral volume controller") + defer klog.Infof("Shutting down ephemeral volume controller") + + if !cache.WaitForNamedCacheSync("ephemeral", ctx.Done(), ec.podSynced, ec.claimsSynced) { + return + } + + for i := 0; i < workers; i++ { + go wait.UntilWithContext(ctx, ec.runWorker, time.Second) + } + + <-ctx.Done() +} + +func (ec *Controller) runWorker(ctx context.Context) { + for ec.processNextWorkItem(ctx) { + } +} + +func (ec *Controller) processNextWorkItem(ctx context.Context) bool { + key, shutdown := ec.queue.Get() + if shutdown { + return false + } + defer ec.queue.Done(key) + + err := ec.syncHandler(ctx, key.(string)) + if err == nil { + ec.queue.Forget(key) + return true + } + + runtime.HandleError(fmt.Errorf("%v failed with: %v", key, err)) + ec.queue.AddRateLimited(key) + + return true +} + +// syncHandler is invoked for each work item which might need to be processed. +// If an error is returned from this function, the item will be requeued. +func (ec *Controller) syncHandler(ctx context.Context, key string) error { + sep := strings.Index(key, ":") + if sep < 0 { + return fmt.Errorf("unexpected key: %s", key) + } + prefix, object := key[0:sep+1], key[sep+1:] + namespace, name, err := cache.SplitMetaNamespaceKey(object) + if err != nil { + return err + } + + switch prefix { + case podKeyPrefix: + return ec.syncPod(ctx, namespace, name) + case claimKeyPrefix: + return ec.syncClaim(ctx, namespace, name) + default: + return fmt.Errorf("unexpected key prefix: %s", prefix) + } + +} + +func (ec *Controller) syncPod(ctx context.Context, namespace, name string) error { + logger := klog.LoggerWithValues(klog.FromContext(ctx), "pod", klog.KRef(namespace, name)) + ctx = klog.NewContext(ctx, logger) + pod, err := ec.podLister.Pods(namespace).Get(name) + if err != nil { + if errors.IsNotFound(err) { + logger.V(5).Info("nothing to do for pod, it is gone") + return nil + } + return err + } + + // Ignore pods which are already getting deleted. + if pod.DeletionTimestamp != nil { + logger.V(5).Info("nothing to do for pod, it is marked for deletion") + return nil + } + + for _, podClaim := range pod.Spec.ResourceClaims { + if err := ec.handleClaim(ctx, pod, podClaim); err != nil { + ec.recorder.Event(pod, v1.EventTypeWarning, "FailedResourceClaimCreation", fmt.Sprintf("PodResourceClaim %s: %v", podClaim.Name, err)) + return fmt.Errorf("pod %s/%s, PodResourceClaim %s: %v", namespace, name, podClaim.Name, err) + } + } + + return nil +} + +// handleResourceClaim is invoked for each volume of a pod. +func (ec *Controller) handleClaim(ctx context.Context, pod *v1.Pod, podClaim v1.PodResourceClaim) error { + logger := klog.LoggerWithValues(klog.FromContext(ctx), "podClaim", podClaim.Name) + ctx = klog.NewContext(ctx, logger) + logger.V(5).Info("checking", "podClaim", podClaim.Name) + templateName := podClaim.Source.ResourceClaimTemplateName + if templateName == nil { + return nil + } + + claimName := resourceclaim.Name(pod, &podClaim) + claim, err := ec.claimLister.ResourceClaims(pod.Namespace).Get(claimName) + if err != nil && !errors.IsNotFound(err) { + return err + } + if claim != nil { + if err := resourceclaim.IsForPod(pod, claim); err != nil { + return err + } + // Already created, nothing more to do. + logger.V(5).Info("claim already created", "podClaim", podClaim.Name, "resourceClaim", claimName) + return nil + } + + template, err := ec.templateLister.ResourceClaimTemplates(pod.Namespace).Get(*templateName) + if err != nil { + return fmt.Errorf("resource claim template %q: %v", *templateName, err) + } + + // Create the ResourceClaim with pod as owner. + isTrue := true + claim = &resourcev1alpha1.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: claimName, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "v1", + Kind: "Pod", + Name: pod.Name, + UID: pod.UID, + Controller: &isTrue, + BlockOwnerDeletion: &isTrue, + }, + }, + Annotations: template.Spec.ObjectMeta.Annotations, + Labels: template.Spec.ObjectMeta.Labels, + }, + Spec: template.Spec.Spec, + } + metrics.ResourceClaimCreateAttempts.Inc() + _, err = ec.kubeClient.ResourceV1alpha1().ResourceClaims(pod.Namespace).Create(ctx, claim, metav1.CreateOptions{}) + if err != nil { + metrics.ResourceClaimCreateFailures.Inc() + return fmt.Errorf("create ResourceClaim %s: %v", claimName, err) + } + return nil +} + +func (ec *Controller) syncClaim(ctx context.Context, namespace, name string) error { + logger := klog.LoggerWithValues(klog.FromContext(ctx), "claim", klog.KRef(namespace, name)) + ctx = klog.NewContext(ctx, logger) + claim, err := ec.claimLister.ResourceClaims(namespace).Get(name) + if err != nil { + if errors.IsNotFound(err) { + logger.V(5).Info("nothing to do for claim, it is gone") + return nil + } + return err + } + + // Check if the ReservedFor entries are all still valid. + valid := make([]resourcev1alpha1.ResourceClaimConsumerReference, 0, len(claim.Status.ReservedFor)) + for _, reservedFor := range claim.Status.ReservedFor { + if reservedFor.APIGroup == "" && + reservedFor.Resource == "pods" { + // A pod falls into one of three categories: + // - we have it in our cache -> don't remove it until we are told that it got removed + // - we don't have it in our cache anymore, but we have seen it before -> it was deleted, remove it + // - not in our cache, not seen -> double-check with API server before removal + + keepEntry := true + + // Tracking deleted pods in the LRU cache is an + // optimization. Without this cache, the code would + // have to do the API call below for every deleted pod + // to ensure that the pod really doesn't exist. With + // the cache, most of the time the pod will be recorded + // as deleted and the API call can be avoided. + if ec.deletedObjects.Has(reservedFor.UID) { + // We know that the pod was deleted. This is + // easy to check and thus is done first. + keepEntry = false + } else { + pod, err := ec.podLister.Pods(claim.Namespace).Get(reservedFor.Name) + if err != nil && !errors.IsNotFound(err) { + return err + } + if pod == nil { + // We might not have it in our informer cache + // yet. Removing the pod while the scheduler is + // scheduling it would be bad. We have to be + // absolutely sure and thus have to check with + // the API server. + pod, err := ec.kubeClient.CoreV1().Pods(claim.Namespace).Get(ctx, reservedFor.Name, metav1.GetOptions{}) + if err != nil && !errors.IsNotFound(err) { + return err + } + if pod == nil || pod.UID != reservedFor.UID { + keepEntry = false + } + } else if pod.UID != reservedFor.UID { + // Pod exists, but is a different incarnation under the same name. + keepEntry = false + } + } + + if keepEntry { + valid = append(valid, reservedFor) + } + continue + } + + // TODO: support generic object lookup + return fmt.Errorf("unsupported ReservedFor entry: %v", reservedFor) + } + + if len(valid) < len(claim.Status.ReservedFor) { + // TODO (#113700): patch + claim := claim.DeepCopy() + claim.Status.ReservedFor = valid + _, err := ec.kubeClient.ResourceV1alpha1().ResourceClaims(claim.Namespace).UpdateStatus(ctx, claim, metav1.UpdateOptions{}) + if err != nil { + return err + } + } + + return nil +} + +// podResourceClaimIndexFunc is an index function that returns ResourceClaim keys (= +// namespace/name) for ResourceClaimTemplates in a given pod. +func podResourceClaimIndexFunc(obj interface{}) ([]string, error) { + pod, ok := obj.(*v1.Pod) + if !ok { + return []string{}, nil + } + keys := []string{} + for _, podClaim := range pod.Spec.ResourceClaims { + if podClaim.Source.ResourceClaimTemplateName != nil { + claimName := resourceclaim.Name(pod, &podClaim) + keys = append(keys, fmt.Sprintf("%s/%s", pod.Namespace, claimName)) + } + } + return keys, nil +} diff --git a/pkg/controller/resourceclaim/controller_test.go b/pkg/controller/resourceclaim/controller_test.go new file mode 100644 index 00000000000..08adf0c8e5b --- /dev/null +++ b/pkg/controller/resourceclaim/controller_test.go @@ -0,0 +1,387 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourceclaim + +import ( + "context" + "errors" + "sort" + "testing" + + "github.com/stretchr/testify/assert" + + v1 "k8s.io/api/core/v1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes/fake" + k8stesting "k8s.io/client-go/testing" + "k8s.io/client-go/tools/cache" + "k8s.io/component-base/metrics/testutil" + "k8s.io/klog/v2" + "k8s.io/kubernetes/pkg/controller" + ephemeralvolumemetrics "k8s.io/kubernetes/pkg/controller/resourceclaim/metrics" +) + +var ( + testPodName = "test-pod" + testNamespace = "my-namespace" + testPodUID = types.UID("uidpod1") + otherNamespace = "not-my-namespace" + podResourceClaimName = "acme-resource" + templateName = "my-template" + className = "my-resource-class" + + testPod = makePod(testPodName, testNamespace, testPodUID) + testPodWithResource = makePod(testPodName, testNamespace, testPodUID, *makePodResourceClaim(podResourceClaimName, templateName)) + otherTestPod = makePod(testPodName+"-II", testNamespace, testPodUID+"-II") + testClaim = makeClaim(testPodName+"-"+podResourceClaimName, testNamespace, className, makeOwnerReference(testPodWithResource, true)) + testClaimReserved = func() *resourcev1alpha1.ResourceClaim { + claim := testClaim.DeepCopy() + claim.Status.ReservedFor = append(claim.Status.ReservedFor, + resourcev1alpha1.ResourceClaimConsumerReference{ + Resource: "pods", + Name: testPodWithResource.Name, + UID: testPodWithResource.UID, + }, + ) + return claim + }() + testClaimReservedTwice = func() *resourcev1alpha1.ResourceClaim { + claim := testClaimReserved.DeepCopy() + claim.Status.ReservedFor = append(claim.Status.ReservedFor, + resourcev1alpha1.ResourceClaimConsumerReference{ + Resource: "pods", + Name: otherTestPod.Name, + UID: otherTestPod.UID, + }, + ) + return claim + }() + conflictingClaim = makeClaim(testPodName+"-"+podResourceClaimName, testNamespace, className, nil) + otherNamespaceClaim = makeClaim(testPodName+"-"+podResourceClaimName, otherNamespace, className, nil) + template = makeTemplate(templateName, testNamespace, className) +) + +func init() { + klog.InitFlags(nil) +} + +func TestSyncHandler(t *testing.T) { + tests := []struct { + name string + key string + claims []*resourcev1alpha1.ResourceClaim + pods []*v1.Pod + podsLater []*v1.Pod + templates []*resourcev1alpha1.ResourceClaimTemplate + expectedClaims []resourcev1alpha1.ResourceClaim + expectedError bool + expectedMetrics expectedMetrics + }{ + { + name: "create", + pods: []*v1.Pod{testPodWithResource}, + templates: []*resourcev1alpha1.ResourceClaimTemplate{template}, + key: podKey(testPodWithResource), + expectedClaims: []resourcev1alpha1.ResourceClaim{*testClaim}, + expectedMetrics: expectedMetrics{1, 0}, + }, + { + name: "missing-template", + pods: []*v1.Pod{testPodWithResource}, + templates: nil, + key: podKey(testPodWithResource), + expectedError: true, + }, + { + name: "nop", + pods: []*v1.Pod{testPodWithResource}, + key: podKey(testPodWithResource), + claims: []*resourcev1alpha1.ResourceClaim{testClaim}, + expectedClaims: []resourcev1alpha1.ResourceClaim{*testClaim}, + expectedMetrics: expectedMetrics{0, 0}, + }, + { + name: "no-such-pod", + key: podKey(testPodWithResource), + }, + { + name: "pod-deleted", + pods: func() []*v1.Pod { + deleted := metav1.Now() + pods := []*v1.Pod{testPodWithResource.DeepCopy()} + pods[0].DeletionTimestamp = &deleted + return pods + }(), + key: podKey(testPodWithResource), + }, + { + name: "no-volumes", + pods: []*v1.Pod{testPod}, + key: podKey(testPod), + }, + { + name: "create-with-other-claim", + pods: []*v1.Pod{testPodWithResource}, + templates: []*resourcev1alpha1.ResourceClaimTemplate{template}, + key: podKey(testPodWithResource), + claims: []*resourcev1alpha1.ResourceClaim{otherNamespaceClaim}, + expectedClaims: []resourcev1alpha1.ResourceClaim{*otherNamespaceClaim, *testClaim}, + expectedMetrics: expectedMetrics{1, 0}, + }, + { + name: "wrong-claim-owner", + pods: []*v1.Pod{testPodWithResource}, + key: podKey(testPodWithResource), + claims: []*resourcev1alpha1.ResourceClaim{conflictingClaim}, + expectedClaims: []resourcev1alpha1.ResourceClaim{*conflictingClaim}, + expectedError: true, + }, + { + name: "create-conflict", + pods: []*v1.Pod{testPodWithResource}, + templates: []*resourcev1alpha1.ResourceClaimTemplate{template}, + key: podKey(testPodWithResource), + expectedMetrics: expectedMetrics{1, 1}, + expectedError: true, + }, + { + name: "stay-reserved-seen", + pods: []*v1.Pod{testPodWithResource}, + key: claimKey(testClaimReserved), + claims: []*resourcev1alpha1.ResourceClaim{testClaimReserved}, + expectedClaims: []resourcev1alpha1.ResourceClaim{*testClaimReserved}, + expectedMetrics: expectedMetrics{0, 0}, + }, + { + name: "stay-reserved-not-seen", + podsLater: []*v1.Pod{testPodWithResource}, + key: claimKey(testClaimReserved), + claims: []*resourcev1alpha1.ResourceClaim{testClaimReserved}, + expectedClaims: []resourcev1alpha1.ResourceClaim{*testClaimReserved}, + expectedMetrics: expectedMetrics{0, 0}, + }, + { + name: "clear-reserved", + pods: []*v1.Pod{}, + key: claimKey(testClaimReserved), + claims: []*resourcev1alpha1.ResourceClaim{testClaimReserved}, + expectedClaims: []resourcev1alpha1.ResourceClaim{*testClaim}, + expectedMetrics: expectedMetrics{0, 0}, + }, + { + name: "remove-reserved", + pods: []*v1.Pod{testPod}, + key: claimKey(testClaimReservedTwice), + claims: []*resourcev1alpha1.ResourceClaim{testClaimReservedTwice}, + expectedClaims: []resourcev1alpha1.ResourceClaim{*testClaimReserved}, + expectedMetrics: expectedMetrics{0, 0}, + }, + } + + for _, tc := range tests { + // Run sequentially because of global logging and global metrics. + t.Run(tc.name, func(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + var objects []runtime.Object + for _, pod := range tc.pods { + objects = append(objects, pod) + } + for _, claim := range tc.claims { + objects = append(objects, claim) + } + for _, template := range tc.templates { + objects = append(objects, template) + } + + fakeKubeClient := createTestClient(objects...) + if tc.expectedMetrics.numFailures > 0 { + fakeKubeClient.PrependReactor("create", "resourceclaims", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { + return true, nil, apierrors.NewConflict(action.GetResource().GroupResource(), "fake name", errors.New("fake conflict")) + }) + } + setupMetrics() + informerFactory := informers.NewSharedInformerFactory(fakeKubeClient, controller.NoResyncPeriodFunc()) + podInformer := informerFactory.Core().V1().Pods() + claimInformer := informerFactory.Resource().V1alpha1().ResourceClaims() + templateInformer := informerFactory.Resource().V1alpha1().ResourceClaimTemplates() + + ec, err := NewController(fakeKubeClient, podInformer, claimInformer, templateInformer) + if err != nil { + t.Fatalf("error creating ephemeral controller : %v", err) + } + + // Ensure informers are up-to-date. + go informerFactory.Start(ctx.Done()) + stopInformers := func() { + cancel() + informerFactory.Shutdown() + } + defer stopInformers() + informerFactory.WaitForCacheSync(ctx.Done()) + cache.WaitForCacheSync(ctx.Done(), podInformer.Informer().HasSynced, claimInformer.Informer().HasSynced, templateInformer.Informer().HasSynced) + + // Simulate race: stop informers, add more pods that the controller doesn't know about. + stopInformers() + for _, pod := range tc.podsLater { + _, err := fakeKubeClient.CoreV1().Pods(pod.Namespace).Create(ctx, pod, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("unexpected error while creating pod: %v", err) + } + } + + err = ec.syncHandler(context.TODO(), tc.key) + if err != nil && !tc.expectedError { + t.Fatalf("unexpected error while running handler: %v", err) + } + if err == nil && tc.expectedError { + t.Fatalf("unexpected success") + } + + claims, err := fakeKubeClient.ResourceV1alpha1().ResourceClaims("").List(ctx, metav1.ListOptions{}) + if err != nil { + t.Fatalf("unexpected error while listing claims: %v", err) + } + assert.Equal(t, normalizeClaims(tc.expectedClaims), normalizeClaims(claims.Items)) + expectMetrics(t, tc.expectedMetrics) + }) + } +} + +func makeClaim(name, namespace, classname string, owner *metav1.OwnerReference) *resourcev1alpha1.ResourceClaim { + claim := &resourcev1alpha1.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace}, + Spec: resourcev1alpha1.ResourceClaimSpec{ + ResourceClassName: classname, + }, + } + if owner != nil { + claim.OwnerReferences = []metav1.OwnerReference{*owner} + } + + return claim +} + +func makePodResourceClaim(name, templateName string) *v1.PodResourceClaim { + return &v1.PodResourceClaim{ + Name: name, + Source: v1.ClaimSource{ + ResourceClaimTemplateName: &templateName, + }, + } +} + +func makePod(name, namespace string, uid types.UID, podClaims ...v1.PodResourceClaim) *v1.Pod { + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace, UID: uid}, + Spec: v1.PodSpec{ + ResourceClaims: podClaims, + }, + } + + return pod +} + +func makeTemplate(name, namespace, classname string) *resourcev1alpha1.ResourceClaimTemplate { + template := &resourcev1alpha1.ResourceClaimTemplate{ + ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace}, + Spec: resourcev1alpha1.ResourceClaimTemplateSpec{ + Spec: resourcev1alpha1.ResourceClaimSpec{ + ResourceClassName: classname, + }, + }, + } + return template +} + +func podKey(pod *v1.Pod) string { + return podKeyPrefix + pod.Namespace + "/" + pod.Name +} + +func claimKey(claim *resourcev1alpha1.ResourceClaim) string { + return claimKeyPrefix + claim.Namespace + "/" + claim.Name +} + +func makeOwnerReference(pod *v1.Pod, isController bool) *metav1.OwnerReference { + isTrue := true + return &metav1.OwnerReference{ + APIVersion: "v1", + Kind: "Pod", + Name: pod.Name, + UID: pod.UID, + Controller: &isController, + BlockOwnerDeletion: &isTrue, + } +} + +func normalizeClaims(claims []resourcev1alpha1.ResourceClaim) []resourcev1alpha1.ResourceClaim { + sort.Slice(claims, func(i, j int) bool { + return claims[i].Namespace < claims[j].Namespace || + claims[i].Name < claims[j].Name + }) + for i := range claims { + if len(claims[i].Status.ReservedFor) == 0 { + claims[i].Status.ReservedFor = nil + } + } + return claims +} + +func createTestClient(objects ...runtime.Object) *fake.Clientset { + fakeClient := fake.NewSimpleClientset(objects...) + return fakeClient +} + +// Metrics helpers + +type expectedMetrics struct { + numCreated int + numFailures int +} + +func expectMetrics(t *testing.T, em expectedMetrics) { + t.Helper() + + actualCreated, err := testutil.GetCounterMetricValue(ephemeralvolumemetrics.ResourceClaimCreateAttempts) + handleErr(t, err, "ResourceClaimCreate") + if actualCreated != float64(em.numCreated) { + t.Errorf("Expected claims to be created %d, got %v", em.numCreated, actualCreated) + } + actualConflicts, err := testutil.GetCounterMetricValue(ephemeralvolumemetrics.ResourceClaimCreateFailures) + handleErr(t, err, "ResourceClaimCreate/Conflict") + if actualConflicts != float64(em.numFailures) { + t.Errorf("Expected claims to have conflicts %d, got %v", em.numFailures, actualConflicts) + } +} + +func handleErr(t *testing.T, err error, metricName string) { + if err != nil { + t.Errorf("Failed to get %s value, err: %v", metricName, err) + } +} + +func setupMetrics() { + ephemeralvolumemetrics.RegisterMetrics() + ephemeralvolumemetrics.ResourceClaimCreateAttempts.Reset() + ephemeralvolumemetrics.ResourceClaimCreateFailures.Reset() +} diff --git a/pkg/controller/resourceclaim/doc.go b/pkg/controller/resourceclaim/doc.go new file mode 100644 index 00000000000..39257887901 --- /dev/null +++ b/pkg/controller/resourceclaim/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package resourceclaim implements the controller part of +// https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3063-dynamic-resource-allocation +// +// It was derived from the generic ephemeral volume controller. +package resourceclaim diff --git a/pkg/controller/resourceclaim/metrics/OWNERS b/pkg/controller/resourceclaim/metrics/OWNERS new file mode 100644 index 00000000000..77fbdc8e594 --- /dev/null +++ b/pkg/controller/resourceclaim/metrics/OWNERS @@ -0,0 +1,6 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +reviewers: + - sig-instrumentation-reviewers +labels: + - sig/instrumentation diff --git a/pkg/controller/resourceclaim/metrics/metrics.go b/pkg/controller/resourceclaim/metrics/metrics.go new file mode 100644 index 00000000000..17c5496cd15 --- /dev/null +++ b/pkg/controller/resourceclaim/metrics/metrics.go @@ -0,0 +1,58 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package metrics + +import ( + "sync" + + "k8s.io/component-base/metrics" + "k8s.io/component-base/metrics/legacyregistry" +) + +// ResourceClaimSubsystem - subsystem name used for ResourceClaim creation +const ResourceClaimSubsystem = "resourceclaim_controller" + +var ( + // ResourceClaimCreateAttempts tracks the number of + // ResourceClaims().Create calls (both successful and unsuccessful) + ResourceClaimCreateAttempts = metrics.NewCounter( + &metrics.CounterOpts{ + Subsystem: ResourceClaimSubsystem, + Name: "create_attempts_total", + Help: "Number of ResourceClaims creation requests", + StabilityLevel: metrics.ALPHA, + }) + // ResourceClaimCreateFailures tracks the number of unsuccessful + // ResourceClaims().Create calls + ResourceClaimCreateFailures = metrics.NewCounter( + &metrics.CounterOpts{ + Subsystem: ResourceClaimSubsystem, + Name: "create_failures_total", + Help: "Number of ResourceClaims creation request failures", + StabilityLevel: metrics.ALPHA, + }) +) + +var registerMetrics sync.Once + +// RegisterMetrics registers ResourceClaim metrics. +func RegisterMetrics() { + registerMetrics.Do(func() { + legacyregistry.MustRegister(ResourceClaimCreateAttempts) + legacyregistry.MustRegister(ResourceClaimCreateFailures) + }) +} diff --git a/pkg/controller/resourceclaim/uid_cache.go b/pkg/controller/resourceclaim/uid_cache.go new file mode 100644 index 00000000000..b07caa5fb3c --- /dev/null +++ b/pkg/controller/resourceclaim/uid_cache.go @@ -0,0 +1,53 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourceclaim + +import ( + "sync" + + "github.com/golang/groupcache/lru" + + "k8s.io/apimachinery/pkg/types" +) + +// uidCache is an LRU cache for uid. +type uidCache struct { + mutex sync.Mutex + cache *lru.Cache +} + +// newUIDCache returns a uidCache. +func newUIDCache(maxCacheEntries int) *uidCache { + return &uidCache{ + cache: lru.New(maxCacheEntries), + } +} + +// Add adds a uid to the cache. +func (c *uidCache) Add(uid types.UID) { + c.mutex.Lock() + defer c.mutex.Unlock() + c.cache.Add(uid, nil) +} + +// Has returns if a uid is in the cache. +func (c *uidCache) Has(uid types.UID) bool { + c.mutex.Lock() + defer c.mutex.Unlock() + _, found := c.cache.Get(uid) + return found +} diff --git a/pkg/controlplane/import_known_versions.go b/pkg/controlplane/import_known_versions.go index b4b275ce82f..6c39ea577ff 100644 --- a/pkg/controlplane/import_known_versions.go +++ b/pkg/controlplane/import_known_versions.go @@ -38,6 +38,7 @@ import ( _ "k8s.io/kubernetes/pkg/apis/node/install" _ "k8s.io/kubernetes/pkg/apis/policy/install" _ "k8s.io/kubernetes/pkg/apis/rbac/install" + _ "k8s.io/kubernetes/pkg/apis/resource/install" _ "k8s.io/kubernetes/pkg/apis/scheduling/install" _ "k8s.io/kubernetes/pkg/apis/storage/install" ) diff --git a/pkg/controlplane/instance.go b/pkg/controlplane/instance.go index da41a5c3565..8936ceea41e 100644 --- a/pkg/controlplane/instance.go +++ b/pkg/controlplane/instance.go @@ -54,6 +54,7 @@ import ( policyapiv1 "k8s.io/api/policy/v1" policyapiv1beta1 "k8s.io/api/policy/v1beta1" rbacv1 "k8s.io/api/rbac/v1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" schedulingapiv1 "k8s.io/api/scheduling/v1" storageapiv1 "k8s.io/api/storage/v1" storageapiv1alpha1 "k8s.io/api/storage/v1alpha1" @@ -108,6 +109,7 @@ import ( noderest "k8s.io/kubernetes/pkg/registry/node/rest" policyrest "k8s.io/kubernetes/pkg/registry/policy/rest" rbacrest "k8s.io/kubernetes/pkg/registry/rbac/rest" + resourcerest "k8s.io/kubernetes/pkg/registry/resource/rest" schedulingrest "k8s.io/kubernetes/pkg/registry/scheduling/rest" storagerest "k8s.io/kubernetes/pkg/registry/storage/rest" ) @@ -435,6 +437,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) appsrest.StorageProvider{}, admissionregistrationrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorization.Authorizer, DiscoveryClient: discoveryClientForAdmissionRegistration}, eventsrest.RESTStorageProvider{TTL: c.ExtraConfig.EventTTL}, + resourcerest.RESTStorageProvider{}, } if err := m.InstallAPIs(c.ExtraConfig.APIResourceConfigSource, c.GenericConfig.RESTOptionsGetter, restStorageProviders...); err != nil { return nil, err @@ -704,6 +707,7 @@ var ( admissionregistrationv1alpha1.SchemeGroupVersion, apiserverinternalv1alpha1.SchemeGroupVersion, authenticationv1alpha1.SchemeGroupVersion, + resourcev1alpha1.SchemeGroupVersion, networkingapiv1alpha1.SchemeGroupVersion, storageapiv1alpha1.SchemeGroupVersion, flowcontrolv1alpha1.SchemeGroupVersion, diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 43f940f5f4f..8847b83094f 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -274,6 +274,14 @@ const ( // Enables usage of hugepages- in downward API. DownwardAPIHugePages featuregate.Feature = "DownwardAPIHugePages" + // owner: @pohly + // kep: http://kep.k8s.io/3063 + // alpha: v1.26 + // + // Enables support for resources with custom parameters and a lifecycle + // that is independent of a Pod. + DynamicResourceAllocation featuregate.Feature = "DynamicResourceAllocation" + // owner: @andrewsykim // kep: https://kep.k8s.io/1672 // alpha: v1.20 @@ -979,6 +987,8 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS EndpointSliceTerminatingCondition: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in v1.28 + DynamicResourceAllocation: {Default: false, PreRelease: featuregate.Alpha}, + EphemeralContainers: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27 EventedPLEG: {Default: false, PreRelease: featuregate.Alpha}, diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 479eb607eb6..7664323f8e4 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -340,6 +340,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "k8s.io/api/core/v1.CephFSVolumeSource": schema_k8sio_api_core_v1_CephFSVolumeSource(ref), "k8s.io/api/core/v1.CinderPersistentVolumeSource": schema_k8sio_api_core_v1_CinderPersistentVolumeSource(ref), "k8s.io/api/core/v1.CinderVolumeSource": schema_k8sio_api_core_v1_CinderVolumeSource(ref), + "k8s.io/api/core/v1.ClaimSource": schema_k8sio_api_core_v1_ClaimSource(ref), "k8s.io/api/core/v1.ClientIPConfig": schema_k8sio_api_core_v1_ClientIPConfig(ref), "k8s.io/api/core/v1.ComponentCondition": schema_k8sio_api_core_v1_ComponentCondition(ref), "k8s.io/api/core/v1.ComponentStatus": schema_k8sio_api_core_v1_ComponentStatus(ref), @@ -460,6 +461,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "k8s.io/api/core/v1.PodPortForwardOptions": schema_k8sio_api_core_v1_PodPortForwardOptions(ref), "k8s.io/api/core/v1.PodProxyOptions": schema_k8sio_api_core_v1_PodProxyOptions(ref), "k8s.io/api/core/v1.PodReadinessGate": schema_k8sio_api_core_v1_PodReadinessGate(ref), + "k8s.io/api/core/v1.PodResourceClaim": schema_k8sio_api_core_v1_PodResourceClaim(ref), "k8s.io/api/core/v1.PodSchedulingGate": schema_k8sio_api_core_v1_PodSchedulingGate(ref), "k8s.io/api/core/v1.PodSecurityContext": schema_k8sio_api_core_v1_PodSecurityContext(ref), "k8s.io/api/core/v1.PodSignature": schema_k8sio_api_core_v1_PodSignature(ref), @@ -485,6 +487,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "k8s.io/api/core/v1.ReplicationControllerList": schema_k8sio_api_core_v1_ReplicationControllerList(ref), "k8s.io/api/core/v1.ReplicationControllerSpec": schema_k8sio_api_core_v1_ReplicationControllerSpec(ref), "k8s.io/api/core/v1.ReplicationControllerStatus": schema_k8sio_api_core_v1_ReplicationControllerStatus(ref), + "k8s.io/api/core/v1.ResourceClaim": schema_k8sio_api_core_v1_ResourceClaim(ref), "k8s.io/api/core/v1.ResourceFieldSelector": schema_k8sio_api_core_v1_ResourceFieldSelector(ref), "k8s.io/api/core/v1.ResourceQuota": schema_k8sio_api_core_v1_ResourceQuota(ref), "k8s.io/api/core/v1.ResourceQuotaList": schema_k8sio_api_core_v1_ResourceQuotaList(ref), @@ -829,6 +832,24 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "k8s.io/api/rbac/v1beta1.RoleList": schema_k8sio_api_rbac_v1beta1_RoleList(ref), "k8s.io/api/rbac/v1beta1.RoleRef": schema_k8sio_api_rbac_v1beta1_RoleRef(ref), "k8s.io/api/rbac/v1beta1.Subject": schema_k8sio_api_rbac_v1beta1_Subject(ref), + "k8s.io/api/resource/v1alpha1.AllocationResult": schema_k8sio_api_resource_v1alpha1_AllocationResult(ref), + "k8s.io/api/resource/v1alpha1.PodScheduling": schema_k8sio_api_resource_v1alpha1_PodScheduling(ref), + "k8s.io/api/resource/v1alpha1.PodSchedulingList": schema_k8sio_api_resource_v1alpha1_PodSchedulingList(ref), + "k8s.io/api/resource/v1alpha1.PodSchedulingSpec": schema_k8sio_api_resource_v1alpha1_PodSchedulingSpec(ref), + "k8s.io/api/resource/v1alpha1.PodSchedulingStatus": schema_k8sio_api_resource_v1alpha1_PodSchedulingStatus(ref), + "k8s.io/api/resource/v1alpha1.ResourceClaim": schema_k8sio_api_resource_v1alpha1_ResourceClaim(ref), + "k8s.io/api/resource/v1alpha1.ResourceClaimConsumerReference": schema_k8sio_api_resource_v1alpha1_ResourceClaimConsumerReference(ref), + "k8s.io/api/resource/v1alpha1.ResourceClaimList": schema_k8sio_api_resource_v1alpha1_ResourceClaimList(ref), + "k8s.io/api/resource/v1alpha1.ResourceClaimParametersReference": schema_k8sio_api_resource_v1alpha1_ResourceClaimParametersReference(ref), + "k8s.io/api/resource/v1alpha1.ResourceClaimSchedulingStatus": schema_k8sio_api_resource_v1alpha1_ResourceClaimSchedulingStatus(ref), + "k8s.io/api/resource/v1alpha1.ResourceClaimSpec": schema_k8sio_api_resource_v1alpha1_ResourceClaimSpec(ref), + "k8s.io/api/resource/v1alpha1.ResourceClaimStatus": schema_k8sio_api_resource_v1alpha1_ResourceClaimStatus(ref), + "k8s.io/api/resource/v1alpha1.ResourceClaimTemplate": schema_k8sio_api_resource_v1alpha1_ResourceClaimTemplate(ref), + "k8s.io/api/resource/v1alpha1.ResourceClaimTemplateList": schema_k8sio_api_resource_v1alpha1_ResourceClaimTemplateList(ref), + "k8s.io/api/resource/v1alpha1.ResourceClaimTemplateSpec": schema_k8sio_api_resource_v1alpha1_ResourceClaimTemplateSpec(ref), + "k8s.io/api/resource/v1alpha1.ResourceClass": schema_k8sio_api_resource_v1alpha1_ResourceClass(ref), + "k8s.io/api/resource/v1alpha1.ResourceClassList": schema_k8sio_api_resource_v1alpha1_ResourceClassList(ref), + "k8s.io/api/resource/v1alpha1.ResourceClassParametersReference": schema_k8sio_api_resource_v1alpha1_ResourceClassParametersReference(ref), "k8s.io/api/scheduling/v1.PriorityClass": schema_k8sio_api_scheduling_v1_PriorityClass(ref), "k8s.io/api/scheduling/v1.PriorityClassList": schema_k8sio_api_scheduling_v1_PriorityClassList(ref), "k8s.io/api/scheduling/v1alpha1.PriorityClass": schema_k8sio_api_scheduling_v1alpha1_PriorityClass(ref), @@ -16385,6 +16406,33 @@ func schema_k8sio_api_core_v1_CinderVolumeSource(ref common.ReferenceCallback) c } } +func schema_k8sio_api_core_v1_ClaimSource(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ClaimSource describes a reference to a ResourceClaim.\n\nExactly one of these fields should be set. Consumers of this type must treat an empty object as if it has an unknown value.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "resourceClaimName": { + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaimName is the name of a ResourceClaim object in the same namespace as this pod.", + Type: []string{"string"}, + Format: "", + }, + }, + "resourceClaimTemplateName": { + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaimTemplateName is the name of a ResourceClaimTemplate object in the same namespace as this pod.\n\nThe template will be used to create a new ResourceClaim, which will be bound to this pod. When this pod is deleted, the ResourceClaim will also be deleted. The name of the ResourceClaim will be -, where is the PodResourceClaim.Name. Pod validation will reject the pod if the concatenated name is not valid for a ResourceClaim (e.g. too long).\n\nAn existing ResourceClaim with that name that is not owned by the pod will not be used for the pod to avoid using an unrelated resource by mistake. Scheduling and pod startup are then blocked until the unrelated ResourceClaim is removed.\n\nThis field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + func schema_k8sio_api_core_v1_ClientIPConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -22907,6 +22955,37 @@ func schema_k8sio_api_core_v1_PodReadinessGate(ref common.ReferenceCallback) com } } +func schema_k8sio_api_core_v1_PodResourceClaim(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "PodResourceClaim references exactly one ResourceClaim through a ClaimSource. It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name uniquely identifies this resource claim inside the pod. This must be a DNS_LABEL.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "source": { + SchemaProps: spec.SchemaProps{ + Description: "Source describes where to find the ResourceClaim.", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/core/v1.ClaimSource"), + }, + }, + }, + Required: []string{"name"}, + }, + }, + Dependencies: []string{ + "k8s.io/api/core/v1.ClaimSource"}, + } +} + func schema_k8sio_api_core_v1_PodSchedulingGate(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -23465,12 +23544,36 @@ func schema_k8sio_api_core_v1_PodSpec(ref common.ReferenceCallback) common.OpenA }, }, }, + "resourceClaims": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "name", + }, + "x-kubernetes-list-type": "map", + "x-kubernetes-patch-merge-key": "name", + "x-kubernetes-patch-strategy": "merge,retainKeys", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaims defines which ResourceClaims must be allocated and reserved before the Pod is allowed to start. The resources will be made available to those containers which consume them by name.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/core/v1.PodResourceClaim"), + }, + }, + }, + }, + }, }, Required: []string{"containers"}, }, }, Dependencies: []string{ - "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.EphemeralContainer", "k8s.io/api/core/v1.HostAlias", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodDNSConfig", "k8s.io/api/core/v1.PodOS", "k8s.io/api/core/v1.PodReadinessGate", "k8s.io/api/core/v1.PodSchedulingGate", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.TopologySpreadConstraint", "k8s.io/api/core/v1.Volume", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, + "k8s.io/api/core/v1.Affinity", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.EphemeralContainer", "k8s.io/api/core/v1.HostAlias", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.PodDNSConfig", "k8s.io/api/core/v1.PodOS", "k8s.io/api/core/v1.PodReadinessGate", "k8s.io/api/core/v1.PodResourceClaim", "k8s.io/api/core/v1.PodSchedulingGate", "k8s.io/api/core/v1.PodSecurityContext", "k8s.io/api/core/v1.Toleration", "k8s.io/api/core/v1.TopologySpreadConstraint", "k8s.io/api/core/v1.Volume", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, } } @@ -24647,6 +24750,28 @@ func schema_k8sio_api_core_v1_ReplicationControllerStatus(ref common.ReferenceCa } } +func schema_k8sio_api_core_v1_ResourceClaim(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaim references one entry in PodSpec.ResourceClaims.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"name"}, + }, + }, + } +} + func schema_k8sio_api_core_v1_ResourceFieldSelector(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -24924,11 +25049,30 @@ func schema_k8sio_api_core_v1_ResourceRequirements(ref common.ReferenceCallback) }, }, }, + "claims": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "set", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/core/v1.ResourceClaim"), + }, + }, + }, + }, + }, }, }, }, Dependencies: []string{ - "k8s.io/apimachinery/pkg/api/resource.Quantity"}, + "k8s.io/api/core/v1.ResourceClaim", "k8s.io/apimachinery/pkg/api/resource.Quantity"}, } } @@ -41279,6 +41423,812 @@ func schema_k8sio_api_rbac_v1beta1_Subject(ref common.ReferenceCallback) common. } } +func schema_k8sio_api_resource_v1alpha1_AllocationResult(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "AllocationResult contains attributed of an allocated resource.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "resourceHandle": { + SchemaProps: spec.SchemaProps{ + Description: "ResourceHandle contains arbitrary data returned by the driver after a successful allocation. This is opaque for Kubernetes. Driver documentation may explain to users how to interpret this data if needed.\n\nThe maximum size of this field is 16KiB. This may get increased in the future, but not reduced.", + Type: []string{"string"}, + Format: "", + }, + }, + "availableOnNodes": { + SchemaProps: spec.SchemaProps{ + Description: "This field will get set by the resource driver after it has allocated the resource driver to inform the scheduler where it can schedule Pods using the ResourceClaim.\n\nSetting this field is optional. If null, the resource is available everywhere.", + Ref: ref("k8s.io/api/core/v1.NodeSelector"), + }, + }, + "shareable": { + SchemaProps: spec.SchemaProps{ + Description: "Shareable determines whether the resource supports more than one consumer at a time.", + Type: []string{"boolean"}, + Format: "", + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/api/core/v1.NodeSelector"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_PodScheduling(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "PodScheduling objects hold information that is needed to schedule a Pod with ResourceClaims that use \"WaitForFirstConsumer\" allocation mode.\n\nThis is an alpha type and requires enabling the DynamicResourceAllocation feature gate.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "Standard object metadata", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "Spec describes where resources for the Pod are needed.", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/resource/v1alpha1.PodSchedulingSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "Status describes where resources for the Pod can be allocated.", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/resource/v1alpha1.PodSchedulingStatus"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "k8s.io/api/resource/v1alpha1.PodSchedulingSpec", "k8s.io/api/resource/v1alpha1.PodSchedulingStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_PodSchedulingList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "PodSchedulingList is a collection of Pod scheduling objects.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "Standard list metadata", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Description: "Items is the list of PodScheduling objects.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/resource/v1alpha1.PodScheduling"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "k8s.io/api/resource/v1alpha1.PodScheduling", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_PodSchedulingSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "PodSchedulingSpec describes where resources for the Pod are needed.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "selectedNode": { + SchemaProps: spec.SchemaProps{ + Description: "SelectedNode is the node for which allocation of ResourceClaims that are referenced by the Pod and that use \"WaitForFirstConsumer\" allocation is to be attempted.", + Type: []string{"string"}, + Format: "", + }, + }, + "potentialNodes": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "set", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "PotentialNodes lists nodes where the Pod might be able to run.\n\nThe size of this field is limited to 128. This is large enough for many clusters. Larger clusters may need more attempts to find a node that suits all pending resources. This may get increased in the future, but not reduced.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func schema_k8sio_api_resource_v1alpha1_PodSchedulingStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "PodSchedulingStatus describes where resources for the Pod can be allocated.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "resourceClaims": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "name", + }, + "x-kubernetes-list-type": "map", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaims describes resource availability for each pod.spec.resourceClaim entry where the corresponding ResourceClaim uses \"WaitForFirstConsumer\" allocation mode.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/resource/v1alpha1.ResourceClaimSchedulingStatus"), + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/api/resource/v1alpha1.ResourceClaimSchedulingStatus"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClaim(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaim describes which resources are needed by a resource consumer. Its status tracks whether the resource has been allocated and what the resulting attributes are.\n\nThis is an alpha type and requires enabling the DynamicResourceAllocation feature gate.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "Standard object metadata", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "Spec describes the desired attributes of a resource that then needs to be allocated. It can only be set once when creating the ResourceClaim.", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/resource/v1alpha1.ResourceClaimSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "Status describes whether the resource is available and with which attributes.", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/resource/v1alpha1.ResourceClaimStatus"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "k8s.io/api/resource/v1alpha1.ResourceClaimSpec", "k8s.io/api/resource/v1alpha1.ResourceClaimStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClaimConsumerReference(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaimConsumerReference contains enough information to let you locate the consumer of a ResourceClaim. The user must be a resource in the same namespace as the ResourceClaim.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "apiGroup": { + SchemaProps: spec.SchemaProps{ + Description: "APIGroup is the group for the resource being referenced. It is empty for the core API. This matches the group in the APIVersion that is used when creating the resources.", + Type: []string{"string"}, + Format: "", + }, + }, + "resource": { + SchemaProps: spec.SchemaProps{ + Description: "Resource is the type of resource being referenced, for example \"pods\".", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name is the name of resource being referenced.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "uid": { + SchemaProps: spec.SchemaProps{ + Description: "UID identifies exactly one incarnation of the resource.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"resource", "name", "uid"}, + }, + }, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClaimList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaimList is a collection of claims.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "Standard list metadata", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Description: "Items is the list of resource claims.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/resource/v1alpha1.ResourceClaim"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "k8s.io/api/resource/v1alpha1.ResourceClaim", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClaimParametersReference(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaimParametersReference contains enough information to let you locate the parameters for a ResourceClaim. The object must be in the same namespace as the ResourceClaim.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "apiGroup": { + SchemaProps: spec.SchemaProps{ + Description: "APIGroup is the group for the resource being referenced. It is empty for the core API. This matches the group in the APIVersion that is used when creating the resources.", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is the type of resource being referenced. This is the same value as in the parameter object's metadata, for example \"ConfigMap\".", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name is the name of resource being referenced.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"kind", "name"}, + }, + }, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClaimSchedulingStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaimSchedulingStatus contains information about one particular ResourceClaim with \"WaitForFirstConsumer\" allocation mode.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name matches the pod.spec.resourceClaims[*].Name field.", + Type: []string{"string"}, + Format: "", + }, + }, + "unsuitableNodes": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "set", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "UnsuitableNodes lists nodes that the ResourceClaim cannot be allocated for.\n\nThe size of this field is limited to 128, the same as for PodSchedulingSpec.PotentialNodes. This may get increased in the future, but not reduced.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClaimSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaimSpec defines how a resource is to be allocated.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "resourceClassName": { + SchemaProps: spec.SchemaProps{ + Description: "ResourceClassName references the driver and additional parameters via the name of a ResourceClass that was created as part of the driver deployment.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "parametersRef": { + SchemaProps: spec.SchemaProps{ + Description: "ParametersRef references a separate object with arbitrary parameters that will be used by the driver when allocating a resource for the claim.\n\nThe object must be in the same namespace as the ResourceClaim.", + Ref: ref("k8s.io/api/resource/v1alpha1.ResourceClaimParametersReference"), + }, + }, + "allocationMode": { + SchemaProps: spec.SchemaProps{ + Description: "Allocation can start immediately or when a Pod wants to use the resource. \"WaitForFirstConsumer\" is the default.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"resourceClassName"}, + }, + }, + Dependencies: []string{ + "k8s.io/api/resource/v1alpha1.ResourceClaimParametersReference"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClaimStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaimStatus tracks whether the resource has been allocated and what the resulting attributes are.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "driverName": { + SchemaProps: spec.SchemaProps{ + Description: "DriverName is a copy of the driver name from the ResourceClass at the time when allocation started.", + Type: []string{"string"}, + Format: "", + }, + }, + "allocation": { + SchemaProps: spec.SchemaProps{ + Description: "Allocation is set by the resource driver once a resource has been allocated successfully. If this is not specified, the resource is not yet allocated.", + Ref: ref("k8s.io/api/resource/v1alpha1.AllocationResult"), + }, + }, + "reservedFor": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "set", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "ReservedFor indicates which entities are currently allowed to use the claim. A Pod which references a ResourceClaim which is not reserved for that Pod will not be started.\n\nThere can be at most 32 such reservations. This may get increased in the future, but not reduced.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/resource/v1alpha1.ResourceClaimConsumerReference"), + }, + }, + }, + }, + }, + "deallocationRequested": { + SchemaProps: spec.SchemaProps{ + Description: "DeallocationRequested indicates that a ResourceClaim is to be deallocated.\n\nThe driver then must deallocate this claim and reset the field together with clearing the Allocation field.\n\nWhile DeallocationRequested is set, no new consumers may be added to ReservedFor.", + Type: []string{"boolean"}, + Format: "", + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/api/resource/v1alpha1.AllocationResult", "k8s.io/api/resource/v1alpha1.ResourceClaimConsumerReference"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClaimTemplate(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaimTemplate is used to produce ResourceClaim objects.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "Standard object metadata", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "Describes the ResourceClaim that is to be generated.\n\nThis field is immutable. A ResourceClaim will get created by the control plane for a Pod when needed and then not get updated anymore.", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/resource/v1alpha1.ResourceClaimTemplateSpec"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "k8s.io/api/resource/v1alpha1.ResourceClaimTemplateSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClaimTemplateList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaimTemplateList is a collection of claim templates.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "Standard list metadata", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Description: "Items is the list of resource claim templates.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/resource/v1alpha1.ResourceClaimTemplate"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "k8s.io/api/resource/v1alpha1.ResourceClaimTemplate", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClaimTemplateSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaimTemplateSpec contains the metadata and fields for a ResourceClaim.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "ObjectMeta may contain labels and annotations that will be copied into the PVC when creating it. No other fields are allowed and will be rejected during validation.", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "Spec for the ResourceClaim. The entire content is copied unchanged into the ResourceClaim that gets created from this template. The same fields as in a ResourceClaim are also valid here.", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/resource/v1alpha1.ResourceClaimSpec"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "k8s.io/api/resource/v1alpha1.ResourceClaimSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClass(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClass is used by administrators to influence how resources are allocated.\n\nThis is an alpha type and requires enabling the DynamicResourceAllocation feature gate.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "Standard object metadata", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "driverName": { + SchemaProps: spec.SchemaProps{ + Description: "DriverName defines the name of the dynamic resource driver that is used for allocation of a ResourceClaim that uses this class.\n\nResource drivers have a unique name in forward domain order (acme.example.com).", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "parametersRef": { + SchemaProps: spec.SchemaProps{ + Description: "ParametersRef references an arbitrary separate object that may hold parameters that will be used by the driver when allocating a resource that uses this class. A dynamic resource driver can distinguish between parameters stored here and and those stored in ResourceClaimSpec.", + Ref: ref("k8s.io/api/resource/v1alpha1.ResourceClassParametersReference"), + }, + }, + "suitableNodes": { + SchemaProps: spec.SchemaProps{ + Description: "Only nodes matching the selector will be considered by the scheduler when trying to find a Node that fits a Pod when that Pod uses a ResourceClaim that has not been allocated yet.\n\nSetting this field is optional. If null, all nodes are candidates.", + Ref: ref("k8s.io/api/core/v1.NodeSelector"), + }, + }, + }, + Required: []string{"driverName"}, + }, + }, + Dependencies: []string{ + "k8s.io/api/core/v1.NodeSelector", "k8s.io/api/resource/v1alpha1.ResourceClassParametersReference", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClassList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClassList is a collection of classes.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "Standard list metadata", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Description: "Items is the list of resource classes.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/resource/v1alpha1.ResourceClass"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "k8s.io/api/resource/v1alpha1.ResourceClass", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_k8sio_api_resource_v1alpha1_ResourceClassParametersReference(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ResourceClassParametersReference contains enough information to let you locate the parameters for a ResourceClass.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "apiGroup": { + SchemaProps: spec.SchemaProps{ + Description: "APIGroup is the group for the resource being referenced. It is empty for the core API. This matches the group in the APIVersion that is used when creating the resources.", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is the type of resource being referenced. This is the same value as in the parameter object's metadata.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name is the name of resource being referenced.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "namespace": { + SchemaProps: spec.SchemaProps{ + Description: "Namespace that contains the referenced resource. Must be empty for cluster-scoped resources and non-empty for namespaced resources.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"kind", "name"}, + }, + }, + } +} + func schema_k8sio_api_scheduling_v1_PriorityClass(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/kubectl/.import-restrictions b/pkg/kubectl/.import-restrictions index 8eb1c93f72a..064a6497011 100644 --- a/pkg/kubectl/.import-restrictions +++ b/pkg/kubectl/.import-restrictions @@ -78,6 +78,9 @@ rules: - k8s.io/kubernetes/pkg/apis/rbac/v1 - k8s.io/kubernetes/pkg/apis/rbac/v1alpha1 - k8s.io/kubernetes/pkg/apis/rbac/v1beta1 + - k8s.io/kubernetes/pkg/apis/resource + - k8s.io/kubernetes/pkg/apis/resource/install + - k8s.io/kubernetes/pkg/apis/resource/v1alpha1 - k8s.io/kubernetes/pkg/apis/scheduling - k8s.io/kubernetes/pkg/apis/scheduling/install - k8s.io/kubernetes/pkg/apis/scheduling/v1alpha1 diff --git a/pkg/kubectl/cmd/convert/import_known_versions.go b/pkg/kubectl/cmd/convert/import_known_versions.go index 6c7ed499f5c..6e261624f55 100644 --- a/pkg/kubectl/cmd/convert/import_known_versions.go +++ b/pkg/kubectl/cmd/convert/import_known_versions.go @@ -38,6 +38,7 @@ import ( _ "k8s.io/kubernetes/pkg/apis/node/install" _ "k8s.io/kubernetes/pkg/apis/policy/install" _ "k8s.io/kubernetes/pkg/apis/rbac/install" + _ "k8s.io/kubernetes/pkg/apis/resource/install" _ "k8s.io/kubernetes/pkg/apis/scheduling/install" _ "k8s.io/kubernetes/pkg/apis/storage/install" diff --git a/pkg/kubelet/cm/container_manager.go b/pkg/kubelet/cm/container_manager.go index f39bb64f66f..82d4640cb44 100644 --- a/pkg/kubelet/cm/container_manager.go +++ b/pkg/kubelet/cm/container_manager.go @@ -22,7 +22,9 @@ import ( "strings" "time" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" + // TODO: Migrate kubelet to either use its own internal objects or client library. v1 "k8s.io/api/core/v1" internalapi "k8s.io/cri-api/pkg/apis" @@ -31,6 +33,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/apis/podresources" "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" "k8s.io/kubernetes/pkg/kubelet/cm/devicemanager" + "k8s.io/kubernetes/pkg/kubelet/cm/dra" "k8s.io/kubernetes/pkg/kubelet/config" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api" @@ -115,6 +118,16 @@ type ContainerManager interface { // GetNodeAllocatableAbsolute returns the absolute value of Node Allocatable which is primarily useful for enforcement. GetNodeAllocatableAbsolute() v1.ResourceList + // PrepareResource prepares pod resources + PrepareResources(pod *v1.Pod, container *v1.Container) (*dra.ContainerInfo, error) + + // UnrepareResources unprepares pod resources + UnprepareResources(*v1.Pod) error + + // PodMightNeedToUnprepareResources returns true if the pod with the given UID + // might need to unprepare resources. + PodMightNeedToUnprepareResources(UID types.UID) bool + // Implements the podresources Provider API for CPUs, Memory and Devices podresources.CPUsProvider podresources.DevicesProvider diff --git a/pkg/kubelet/cm/container_manager_linux.go b/pkg/kubelet/cm/container_manager_linux.go index dfbfc2f7325..332e99e72ee 100644 --- a/pkg/kubelet/cm/container_manager_linux.go +++ b/pkg/kubelet/cm/container_manager_linux.go @@ -39,10 +39,12 @@ import ( libcontaineruserns "github.com/opencontainers/runc/libcontainer/userns" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" utilfeature "k8s.io/apiserver/pkg/util/feature" + clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/record" utilsysctl "k8s.io/component-helpers/node/util/sysctl" internalapi "k8s.io/cri-api/pkg/apis" @@ -53,6 +55,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/cm/containermap" "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager" "k8s.io/kubernetes/pkg/kubelet/cm/devicemanager" + "k8s.io/kubernetes/pkg/kubelet/cm/dra" "k8s.io/kubernetes/pkg/kubelet/cm/memorymanager" memorymanagerstate "k8s.io/kubernetes/pkg/kubelet/cm/memorymanager/state" "k8s.io/kubernetes/pkg/kubelet/cm/topologymanager" @@ -128,6 +131,8 @@ type containerManagerImpl struct { memoryManager memorymanager.Manager // Interface for Topology resource co-ordination topologyManager topologymanager.Manager + // Interface for Dynamic Resource Allocation management. + draManager dra.Manager } type features struct { @@ -195,7 +200,7 @@ func validateSystemRequirements(mountUtil mount.Interface) (features, error) { // TODO(vmarmol): Add limits to the system containers. // Takes the absolute name of the specified containers. // Empty container name disables use of the specified container. -func NewContainerManager(mountUtil mount.Interface, cadvisorInterface cadvisor.Interface, nodeConfig NodeConfig, failSwapOn bool, recorder record.EventRecorder) (ContainerManager, error) { +func NewContainerManager(mountUtil mount.Interface, cadvisorInterface cadvisor.Interface, nodeConfig NodeConfig, failSwapOn bool, recorder record.EventRecorder, kubeClient clientset.Interface) (ContainerManager, error) { subsystems, err := GetCgroupSubsystems() if err != nil { return nil, fmt.Errorf("failed to get mounted cgroup subsystems: %v", err) @@ -307,6 +312,15 @@ func NewContainerManager(mountUtil mount.Interface, cadvisorInterface cadvisor.I } cm.topologyManager.AddHintProvider(cm.deviceManager) + // initialize DRA manager + if utilfeature.DefaultFeatureGate.Enabled(kubefeatures.DynamicResourceAllocation) { + klog.InfoS("Creating Dynamic Resource Allocation (DRA) manager") + cm.draManager, err = dra.NewManagerImpl(kubeClient) + if err != nil { + return nil, err + } + } + // Initialize CPU manager cm.cpuManager, err = cpumanager.NewManager( nodeConfig.CPUManagerPolicy, @@ -642,6 +656,13 @@ func (cm *containerManagerImpl) GetPluginRegistrationHandler() cache.PluginHandl // TODO: move the GetResources logic to PodContainerManager. func (cm *containerManagerImpl) GetResources(pod *v1.Pod, container *v1.Container) (*kubecontainer.RunContainerOptions, error) { opts := &kubecontainer.RunContainerOptions{} + if cm.draManager != nil { + resOpts, err := cm.PrepareResources(pod, container) + if err != nil { + return nil, err + } + opts.Annotations = append(opts.Annotations, resOpts.Annotations...) + } // Allocate should already be called during predicateAdmitHandler.Admit(), // just try to fetch device runtime information from cached state here devOpts, err := cm.deviceManager.GetDeviceRunContainerOptions(pod, container) @@ -671,13 +692,14 @@ func (cm *containerManagerImpl) GetAllocateResourcesPodAdmitHandler() lifecycle. // work as we add more and more hint providers that the TopologyManager // needs to call Allocate() on (that may not be directly intstantiated // inside this component). - return &resourceAllocator{cm.cpuManager, cm.memoryManager, cm.deviceManager} + return &resourceAllocator{cm.cpuManager, cm.memoryManager, cm.deviceManager, cm.draManager} } type resourceAllocator struct { cpuManager cpumanager.Manager memoryManager memorymanager.Manager deviceManager devicemanager.Manager + draManager dra.Manager } func (m *resourceAllocator) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult { @@ -1009,3 +1031,19 @@ func containerMemoryFromBlock(blocks []memorymanagerstate.Block) []*podresources return containerMemories } + +func (cm *containerManagerImpl) PrepareResources(pod *v1.Pod, container *v1.Container) (*dra.ContainerInfo, error) { + return cm.draManager.PrepareResources(pod, container) +} + +func (cm *containerManagerImpl) UnprepareResources(pod *v1.Pod) error { + return cm.draManager.UnprepareResources(pod) +} + +func (cm *containerManagerImpl) PodMightNeedToUnprepareResources(UID types.UID) bool { + if cm.draManager != nil { + return cm.draManager.PodMightNeedToUnprepareResources(UID) + } + + return false +} diff --git a/pkg/kubelet/cm/container_manager_stub.go b/pkg/kubelet/cm/container_manager_stub.go index 6bd5f3e3689..4b2c1f87e8f 100644 --- a/pkg/kubelet/cm/container_manager_stub.go +++ b/pkg/kubelet/cm/container_manager_stub.go @@ -21,9 +21,11 @@ import ( "k8s.io/klog/v2" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/types" internalapi "k8s.io/cri-api/pkg/apis" podresourcesapi "k8s.io/kubelet/pkg/apis/podresources/v1" "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager" + "k8s.io/kubernetes/pkg/kubelet/cm/dra" "k8s.io/kubernetes/pkg/kubelet/cm/memorymanager" "k8s.io/kubernetes/pkg/kubelet/cm/topologymanager" "k8s.io/kubernetes/pkg/kubelet/config" @@ -154,6 +156,18 @@ func (cm *containerManagerStub) GetNodeAllocatableAbsolute() v1.ResourceList { return nil } +func (cm *containerManagerStub) PrepareResources(pod *v1.Pod, container *v1.Container) (*dra.ContainerInfo, error) { + return nil, nil +} + +func (cm *containerManagerStub) UnprepareResources(*v1.Pod) error { + return nil +} + +func (cm *containerManagerStub) PodMightNeedToUnprepareResources(UID types.UID) bool { + return false +} + func NewStubContainerManager() ContainerManager { return &containerManagerStub{shouldResetExtendedResourceCapacity: false} } diff --git a/pkg/kubelet/cm/container_manager_unsupported.go b/pkg/kubelet/cm/container_manager_unsupported.go index e58c236b50f..ba4f9a1b6ad 100644 --- a/pkg/kubelet/cm/container_manager_unsupported.go +++ b/pkg/kubelet/cm/container_manager_unsupported.go @@ -25,6 +25,7 @@ import ( "k8s.io/mount-utils" v1 "k8s.io/api/core/v1" + clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/record" internalapi "k8s.io/cri-api/pkg/apis" "k8s.io/kubernetes/pkg/kubelet/cadvisor" @@ -42,6 +43,6 @@ func (unsupportedContainerManager) Start(_ *v1.Node, _ ActivePodsFunc, _ config. return fmt.Errorf("Container Manager is unsupported in this build") } -func NewContainerManager(_ mount.Interface, _ cadvisor.Interface, _ NodeConfig, failSwapOn bool, recorder record.EventRecorder) (ContainerManager, error) { +func NewContainerManager(_ mount.Interface, _ cadvisor.Interface, _ NodeConfig, failSwapOn bool, recorder record.EventRecorder, kubeClient clientset.Interface) (ContainerManager, error) { return &unsupportedContainerManager{}, nil } diff --git a/pkg/kubelet/cm/container_manager_windows.go b/pkg/kubelet/cm/container_manager_windows.go index 742506a78b4..c34c8432527 100644 --- a/pkg/kubelet/cm/container_manager_windows.go +++ b/pkg/kubelet/cm/container_manager_windows.go @@ -30,6 +30,8 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/types" + clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/record" internalapi "k8s.io/cri-api/pkg/apis" podresourcesapi "k8s.io/kubelet/pkg/apis/podresources/v1" @@ -37,6 +39,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/cm/admission" "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager" "k8s.io/kubernetes/pkg/kubelet/cm/devicemanager" + "k8s.io/kubernetes/pkg/kubelet/cm/dra" "k8s.io/kubernetes/pkg/kubelet/cm/memorymanager" "k8s.io/kubernetes/pkg/kubelet/cm/topologymanager" "k8s.io/kubernetes/pkg/kubelet/config" @@ -93,7 +96,7 @@ func (cm *containerManagerImpl) Start(node *v1.Node, } // NewContainerManager creates windows container manager. -func NewContainerManager(mountUtil mount.Interface, cadvisorInterface cadvisor.Interface, nodeConfig NodeConfig, failSwapOn bool, recorder record.EventRecorder) (ContainerManager, error) { +func NewContainerManager(mountUtil mount.Interface, cadvisorInterface cadvisor.Interface, nodeConfig NodeConfig, failSwapOn bool, recorder record.EventRecorder, kubeClient clientset.Interface) (ContainerManager, error) { // It is safe to invoke `MachineInfo` on cAdvisor before logically initializing cAdvisor here because // machine info is computed and cached once as part of cAdvisor object creation. // But `RootFsInfo` and `ImagesFsInfo` are not available at this moment so they will be called later during manager starts @@ -250,3 +253,15 @@ func (cm *containerManagerImpl) GetAllocatableMemory() []*podresourcesapi.Contai func (cm *containerManagerImpl) GetNodeAllocatableAbsolute() v1.ResourceList { return nil } + +func (cm *containerManagerImpl) PrepareResources(pod *v1.Pod, container *v1.Container) (*dra.ContainerInfo, error) { + return nil, nil +} + +func (cm *containerManagerImpl) UnprepareResources(*v1.Pod) error { + return nil +} + +func (cm *containerManagerImpl) PodMightNeedToUnprepareResources(UID types.UID) bool { + return false +} diff --git a/pkg/kubelet/cm/dra/cdi.go b/pkg/kubelet/cm/dra/cdi.go new file mode 100644 index 00000000000..3d80891f9d2 --- /dev/null +++ b/pkg/kubelet/cm/dra/cdi.go @@ -0,0 +1,283 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// The code below was copied from +// https://github.com/container-orchestrated-devices/container-device-interface/blob/v0.5.3/pkg/cdi/annotations.go +// https://github.com/container-orchestrated-devices/container-device-interface/blob/v0.5.3/pkg/cdi/qualified-device.go +// to avoid a dependency on that package and the indirect dependencies that +// this would have implied. +// +// Long term it would be good to avoid this duplication: +// https://github.com/container-orchestrated-devices/container-device-interface/issues/97 + +package dra + +import ( + "errors" + "fmt" + "strings" +) + +const ( + // annotationPrefix is the prefix for CDI container annotation keys. + annotationPrefix = "cdi.k8s.io/" +) + +// updateAnnotations updates annotations with a plugin-specific CDI device +// injection request for the given devices. Upon any error a non-nil error +// is returned and annotations are left intact. By convention plugin should +// be in the format of "vendor.device-type". +func updateAnnotations(annotations map[string]string, plugin string, deviceID string, devices []string) (map[string]string, error) { + key, err := annotationKey(plugin, deviceID) + if err != nil { + return annotations, fmt.Errorf("CDI annotation failed: %v", err) + } + if _, ok := annotations[key]; ok { + return annotations, fmt.Errorf("CDI annotation failed, key %q used", key) + } + value, err := annotationValue(devices) + if err != nil { + return annotations, fmt.Errorf("CDI annotation failed: %v", err) + } + + if annotations == nil { + annotations = make(map[string]string) + } + annotations[key] = value + + return annotations, nil +} + +// annotationKey returns a unique annotation key for an device allocation +// by a K8s device plugin. pluginName should be in the format of +// "vendor.device-type". deviceID is the ID of the device the plugin is +// allocating. It is used to make sure that the generated key is unique +// even if multiple allocations by a single plugin needs to be annotated. +func annotationKey(pluginName, deviceID string) (string, error) { + const maxNameLen = 63 + + if pluginName == "" { + return "", errors.New("invalid plugin name, empty") + } + if deviceID == "" { + return "", errors.New("invalid deviceID, empty") + } + + name := pluginName + "_" + strings.ReplaceAll(deviceID, "/", "_") + + if len(name) > maxNameLen { + return "", fmt.Errorf("invalid plugin+deviceID %q, too long", name) + } + + if c := rune(name[0]); !isAlphaNumeric(c) { + return "", fmt.Errorf("invalid name %q, first '%c' should be alphanumeric", name, c) + } + if len(name) > 2 { + for _, c := range name[1 : len(name)-1] { + switch { + case isAlphaNumeric(c): + case c == '_' || c == '-' || c == '.': + default: + return "", fmt.Errorf("invalid name %q, invalid charcter '%c'", name, c) + } + } + } + if c := rune(name[len(name)-1]); !isAlphaNumeric(c) { + return "", fmt.Errorf("invalid name %q, last '%c' should be alphanumeric", name, c) + } + + return annotationPrefix + name, nil +} + +// annotationValue returns an annotation value for the given devices. +func annotationValue(devices []string) (string, error) { + value, sep := "", "" + for _, d := range devices { + if _, _, _, err := parseQualifiedName(d); err != nil { + return "", err + } + value += sep + d + sep = "," + } + + return value, nil +} + +// parseQualifiedName splits a qualified name into device vendor, class, +// and name. If the device fails to parse as a qualified name, or if any +// of the split components fail to pass syntax validation, vendor and +// class are returned as empty, together with the verbatim input as the +// name and an error describing the reason for failure. +func parseQualifiedName(device string) (string, string, string, error) { + vendor, class, name := parseDevice(device) + + if vendor == "" { + return "", "", device, fmt.Errorf("unqualified device %q, missing vendor", device) + } + if class == "" { + return "", "", device, fmt.Errorf("unqualified device %q, missing class", device) + } + if name == "" { + return "", "", device, fmt.Errorf("unqualified device %q, missing device name", device) + } + + if err := validateVendorName(vendor); err != nil { + return "", "", device, fmt.Errorf("invalid device %q: %v", device, err) + } + if err := validateClassName(class); err != nil { + return "", "", device, fmt.Errorf("invalid device %q: %v", device, err) + } + if err := validateDeviceName(name); err != nil { + return "", "", device, fmt.Errorf("invalid device %q: %v", device, err) + } + + return vendor, class, name, nil +} + +// parseDevice tries to split a device name into vendor, class, and name. +// If this fails, for instance in the case of unqualified device names, +// parseDevice returns an empty vendor and class together with name set +// to the verbatim input. +func parseDevice(device string) (string, string, string) { + if device == "" || device[0] == '/' { + return "", "", device + } + + parts := strings.SplitN(device, "=", 2) + if len(parts) != 2 || parts[0] == "" || parts[1] == "" { + return "", "", device + } + + name := parts[1] + vendor, class := parseQualifier(parts[0]) + if vendor == "" { + return "", "", device + } + + return vendor, class, name +} + +// parseQualifier splits a device qualifier into vendor and class. +// The syntax for a device qualifier is +// +// "/" +// +// If parsing fails, an empty vendor and the class set to the +// verbatim input is returned. +func parseQualifier(kind string) (string, string) { + parts := strings.SplitN(kind, "/", 2) + if len(parts) != 2 || parts[0] == "" || parts[1] == "" { + return "", kind + } + return parts[0], parts[1] +} + +// validateVendorName checks the validity of a vendor name. +// A vendor name may contain the following ASCII characters: +// - upper- and lowercase letters ('A'-'Z', 'a'-'z') +// - digits ('0'-'9') +// - underscore, dash, and dot ('_', '-', and '.') +func validateVendorName(vendor string) error { + if vendor == "" { + return fmt.Errorf("invalid (empty) vendor name") + } + if !isLetter(rune(vendor[0])) { + return fmt.Errorf("invalid vendor %q, should start with letter", vendor) + } + for _, c := range string(vendor[1 : len(vendor)-1]) { + switch { + case isAlphaNumeric(c): + case c == '_' || c == '-' || c == '.': + default: + return fmt.Errorf("invalid character '%c' in vendor name %q", + c, vendor) + } + } + if !isAlphaNumeric(rune(vendor[len(vendor)-1])) { + return fmt.Errorf("invalid vendor %q, should end with a letter or digit", vendor) + } + + return nil +} + +// validateClassName checks the validity of class name. +// A class name may contain the following ASCII characters: +// - upper- and lowercase letters ('A'-'Z', 'a'-'z') +// - digits ('0'-'9') +// - underscore and dash ('_', '-') +func validateClassName(class string) error { + if class == "" { + return fmt.Errorf("invalid (empty) device class") + } + if !isLetter(rune(class[0])) { + return fmt.Errorf("invalid class %q, should start with letter", class) + } + for _, c := range string(class[1 : len(class)-1]) { + switch { + case isAlphaNumeric(c): + case c == '_' || c == '-': + default: + return fmt.Errorf("invalid character '%c' in device class %q", + c, class) + } + } + if !isAlphaNumeric(rune(class[len(class)-1])) { + return fmt.Errorf("invalid class %q, should end with a letter or digit", class) + } + return nil +} + +// validateDeviceName checks the validity of a device name. +// A device name may contain the following ASCII characters: +// - upper- and lowercase letters ('A'-'Z', 'a'-'z') +// - digits ('0'-'9') +// - underscore, dash, dot, colon ('_', '-', '.', ':') +func validateDeviceName(name string) error { + if name == "" { + return fmt.Errorf("invalid (empty) device name") + } + if !isAlphaNumeric(rune(name[0])) { + return fmt.Errorf("invalid class %q, should start with a letter or digit", name) + } + if len(name) == 1 { + return nil + } + for _, c := range string(name[1 : len(name)-1]) { + switch { + case isAlphaNumeric(c): + case c == '_' || c == '-' || c == '.' || c == ':': + default: + return fmt.Errorf("invalid character '%c' in device name %q", + c, name) + } + } + if !isAlphaNumeric(rune(name[len(name)-1])) { + return fmt.Errorf("invalid name %q, should end with a letter or digit", name) + } + return nil +} + +func isLetter(c rune) bool { + return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') +} + +func isDigit(c rune) bool { + return '0' <= c && c <= '9' +} + +func isAlphaNumeric(c rune) bool { + return isLetter(c) || isDigit(c) +} diff --git a/pkg/kubelet/cm/dra/claiminfo.go b/pkg/kubelet/cm/dra/claiminfo.go new file mode 100644 index 00000000000..354f8c8bc43 --- /dev/null +++ b/pkg/kubelet/cm/dra/claiminfo.go @@ -0,0 +1,127 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dra + +import ( + "fmt" + "sync" + + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/sets" + kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" +) + +// claimInfo holds information required +// to prepare and unprepare a resource claim. +type claimInfo struct { + sync.RWMutex + + // name of the DRA driver + driverName string + + // claimUID is an UID of the resource claim + claimUID types.UID + + // claimName is a name of the resource claim + claimName string + + // namespace is a claim namespace + namespace string + + // podUIDs is a set of pod UIDs that reference a resource + podUIDs sets.Set[string] + + // cdiDevices is a list of CDI devices returned by the + // GRPC API call NodePrepareResource + cdiDevices []string + + // annotations is a list of container annotations associated with + // a prepared resource + annotations []kubecontainer.Annotation +} + +func (res *claimInfo) addPodReference(podUID types.UID) { + res.Lock() + defer res.Unlock() + + res.podUIDs.Insert(string(podUID)) +} + +func (res *claimInfo) deletePodReference(podUID types.UID) { + res.Lock() + defer res.Unlock() + + res.podUIDs.Delete(string(podUID)) +} + +// claimInfoCache is a cache of processed resource claims keyed by namespace + claim name. +type claimInfoCache struct { + sync.RWMutex + claimInfo map[string]*claimInfo +} + +// newClaimInfoCache is a function that returns an instance of the claimInfoCache. +func newClaimInfoCache() *claimInfoCache { + return &claimInfoCache{ + claimInfo: make(map[string]*claimInfo), + } +} + +func (cache *claimInfoCache) add(claim, namespace string, res *claimInfo) error { + cache.Lock() + defer cache.Unlock() + + key := claim + namespace + if _, ok := cache.claimInfo[key]; ok { + return fmt.Errorf("claim %s, namespace %s already cached", claim, namespace) + } + + cache.claimInfo[claim+namespace] = res + + return nil +} + +func (cache *claimInfoCache) get(claimName, namespace string) *claimInfo { + cache.RLock() + defer cache.RUnlock() + + return cache.claimInfo[claimName+namespace] +} + +func (cache *claimInfoCache) delete(claimName, namespace string) { + cache.Lock() + defer cache.Unlock() + + delete(cache.claimInfo, claimName+namespace) +} + +// hasPodReference checks if there is at least one claim +// that is referenced by the pod with the given UID +// This function is used indirectly by the status manager +// to check if pod can enter termination status +func (cache *claimInfoCache) hasPodReference(UID types.UID) bool { + cache.RLock() + defer cache.RUnlock() + + for _, claimInfo := range cache.claimInfo { + if claimInfo.podUIDs.Has(string(UID)) { + return true + } + } + + return false +} diff --git a/pkg/kubelet/cm/dra/manager.go b/pkg/kubelet/cm/dra/manager.go new file mode 100644 index 00000000000..6e702023516 --- /dev/null +++ b/pkg/kubelet/cm/dra/manager.go @@ -0,0 +1,255 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dra + +import ( + "context" + "fmt" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/sets" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/dynamic-resource-allocation/resourceclaim" + "k8s.io/klog/v2" + dra "k8s.io/kubernetes/pkg/kubelet/cm/dra/plugin" + kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" +) + +// ManagerImpl is the structure in charge of managing DRA resource Plugins. +type ManagerImpl struct { + // cache contains cached claim info + cache *claimInfoCache + + // KubeClient reference + kubeClient clientset.Interface +} + +// NewManagerImpl creates a new manager. +func NewManagerImpl(kubeClient clientset.Interface) (*ManagerImpl, error) { + klog.V(2).InfoS("Creating DRA manager") + + manager := &ManagerImpl{ + cache: newClaimInfoCache(), + kubeClient: kubeClient, + } + + return manager, nil +} + +// Generate container annotations using CDI UpdateAnnotations API. +func generateCDIAnnotations( + claimUID types.UID, + driverName string, + cdiDevices []string, +) ([]kubecontainer.Annotation, error) { + annotations, err := updateAnnotations(map[string]string{}, driverName, string(claimUID), cdiDevices) + if err != nil { + return nil, fmt.Errorf("can't generate CDI annotations: %+v", err) + } + + kubeAnnotations := []kubecontainer.Annotation{} + for key, value := range annotations { + kubeAnnotations = append(kubeAnnotations, kubecontainer.Annotation{Name: key, Value: value}) + } + + return kubeAnnotations, nil +} + +// prepareContainerResources attempts to prepare all of required resource +// plugin resources for the input container, issue an NodePrepareResource rpc request +// for each new resource requirement, process their responses and update the cached +// containerResources on success. +func (m *ManagerImpl) prepareContainerResources(pod *v1.Pod, container *v1.Container) error { + // Process resources for each resource claim referenced by container + for range container.Resources.Claims { + for i, podResourceClaim := range pod.Spec.ResourceClaims { + claimName := resourceclaim.Name(pod, &pod.Spec.ResourceClaims[i]) + klog.V(3).InfoS("Processing resource", "claim", claimName, "pod", pod.Name) + + if claimInfo := m.cache.get(claimName, pod.Namespace); claimInfo != nil { + // resource is already prepared, add pod UID to it + claimInfo.addPodReference(pod.UID) + + continue + } + + // Query claim object from the API server + resourceClaim, err := m.kubeClient.ResourceV1alpha1().ResourceClaims(pod.Namespace).Get( + context.TODO(), + claimName, + metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("failed to fetch ResourceClaim %s referenced by pod %s: %+v", claimName, pod.Name, err) + } + + // Check if pod is in the ReservedFor for the claim + if !resourceclaim.IsReservedForPod(pod, resourceClaim) { + return fmt.Errorf("pod %s(%s) is not allowed to use resource claim %s(%s)", + pod.Name, pod.UID, podResourceClaim.Name, resourceClaim.UID) + } + + // Call NodePrepareResource RPC + driverName := resourceClaim.Status.DriverName + + client, err := dra.NewDRAPluginClient(driverName) + if err != nil { + return fmt.Errorf("failed to get DRA Plugin client for plugin name %s, err=%+v", driverName, err) + } + + response, err := client.NodePrepareResource( + context.Background(), + resourceClaim.Namespace, + resourceClaim.UID, + resourceClaim.Name, + resourceClaim.Status.Allocation.ResourceHandle) + if err != nil { + return fmt.Errorf("NodePrepareResource failed, claim UID: %s, claim name: %s, resource handle: %s, err: %+v", + resourceClaim.UID, resourceClaim.Name, resourceClaim.Status.Allocation.ResourceHandle, err) + } + + klog.V(3).InfoS("NodePrepareResource succeeded", "response", response) + + annotations, err := generateCDIAnnotations(resourceClaim.UID, driverName, response.CdiDevices) + if err != nil { + return fmt.Errorf("failed to generate container annotations, err: %+v", err) + } + + // Cache prepared resource + err = m.cache.add( + resourceClaim.Name, + resourceClaim.Namespace, + &claimInfo{ + driverName: driverName, + claimUID: resourceClaim.UID, + claimName: resourceClaim.Name, + namespace: resourceClaim.Namespace, + podUIDs: sets.New(string(pod.UID)), + cdiDevices: response.CdiDevices, + annotations: annotations, + }) + if err != nil { + return fmt.Errorf( + "failed to cache prepared resource, claim: %s(%s), err: %+v", + resourceClaim.Name, + resourceClaim.UID, + err, + ) + } + } + } + + return nil +} + +// getContainerInfo gets a container info from the claimInfo cache. +// This information is used by the caller to update a container config. +func (m *ManagerImpl) getContainerInfo(pod *v1.Pod, container *v1.Container) (*ContainerInfo, error) { + annotations := []kubecontainer.Annotation{} + + for i, podResourceClaim := range pod.Spec.ResourceClaims { + claimName := resourceclaim.Name(pod, &pod.Spec.ResourceClaims[i]) + + for _, claim := range container.Resources.Claims { + if podResourceClaim.Name != claim.Name { + continue + } + + claimInfo := m.cache.get(claimName, pod.Namespace) + if claimInfo == nil { + return nil, fmt.Errorf("unable to get resource for namespace: %s, claim: %s", pod.Namespace, claimName) + } + + klog.V(3).InfoS("add resource annotations", "claim", claimName, "annotations", claimInfo.annotations) + annotations = append(annotations, claimInfo.annotations...) + } + } + + return &ContainerInfo{Annotations: annotations}, nil +} + +// PrepareResources calls plugin NodePrepareResource from the registered DRA resource plugins. +func (m *ManagerImpl) PrepareResources(pod *v1.Pod, container *v1.Container) (*ContainerInfo, error) { + if err := m.prepareContainerResources(pod, container); err != nil { + return nil, err + } + + return m.getContainerInfo(pod, container) +} + +// UnprepareResources calls a plugin's NodeUnprepareResource API for each resource claim owned by a pod. +// This function is idempotent and may be called multiple times against the same pod. +// As such, calls to the underlying NodeUnprepareResource API are skipped for claims that have +// already been successfully unprepared. +func (m *ManagerImpl) UnprepareResources(pod *v1.Pod) error { + // Call NodeUnprepareResource RPC for every resource claim referenced by the pod + for i := range pod.Spec.ResourceClaims { + claimName := resourceclaim.Name(pod, &pod.Spec.ResourceClaims[i]) + claimInfo := m.cache.get(claimName, pod.Namespace) + + // Skip calling NodeUnprepareResource if claim info is not cached + if claimInfo == nil { + continue + } + + // Skip calling NodeUnprepareResource if other pods are still referencing it + if len(claimInfo.podUIDs) > 1 { + claimInfo.deletePodReference(pod.UID) + continue + } + + // Call NodeUnprepareResource only for the last pod that references the claim + client, err := dra.NewDRAPluginClient(claimInfo.driverName) + if err != nil { + return fmt.Errorf("failed to get DRA Plugin client for plugin name %s, err=%+v", claimInfo.driverName, err) + } + + response, err := client.NodeUnprepareResource( + context.Background(), + claimInfo.namespace, + claimInfo.claimUID, + claimInfo.claimName, + claimInfo.cdiDevices) + if err != nil { + return fmt.Errorf( + "NodeUnprepareResource failed, pod: %s, claim UID: %s, claim name: %s, CDI devices: %s, err: %+v", + pod.Name, + claimInfo.claimUID, + claimInfo.claimName, + claimInfo.cdiDevices, err) + } + + // Delete last pod UID only if NodeUnprepareResource call succeeds. + // This ensures that status manager doesn't enter termination status + // for the pod. This logic is implemented in the m.PodMightNeedToUnprepareResources + // and in the claimInfo.hasPodReference. + claimInfo.deletePodReference(pod.UID) + + klog.V(3).InfoS("NodeUnprepareResource succeeded", "response", response) + // delete resource from the cache + m.cache.delete(claimInfo.claimName, pod.Namespace) + } + + return nil +} + +// PodMightNeedToUnprepareResources returns true if the pod might need to +// unprepare resources +func (m *ManagerImpl) PodMightNeedToUnprepareResources(UID types.UID) bool { + return m.cache.hasPodReference(UID) +} diff --git a/pkg/kubelet/cm/dra/plugin/client.go b/pkg/kubelet/cm/dra/plugin/client.go new file mode 100644 index 00000000000..49ab5cb1e3c --- /dev/null +++ b/pkg/kubelet/cm/dra/plugin/client.go @@ -0,0 +1,182 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package plugin + +import ( + "context" + "errors" + "fmt" + "io" + "net" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "k8s.io/apimachinery/pkg/types" + "k8s.io/klog/v2" + + drapbv1 "k8s.io/kubelet/pkg/apis/dra/v1alpha1" +) + +type Client interface { + NodePrepareResource( + ctx context.Context, + namespace string, + claimUID types.UID, + claimName string, + resourceHandle string, + ) (*drapbv1.NodePrepareResourceResponse, error) + + NodeUnprepareResource( + ctx context.Context, + namespace string, + claimUID types.UID, + claimName string, + cdiDevice []string, + ) (*drapbv1.NodeUnprepareResourceResponse, error) +} + +// Strongly typed address. +type draAddr string + +// draPluginClient encapsulates all dra plugin methods. +type draPluginClient struct { + pluginName string + addr draAddr + nodeV1ClientCreator nodeV1ClientCreator +} + +var _ Client = &draPluginClient{} + +type nodeV1ClientCreator func(addr draAddr) ( + nodeClient drapbv1.NodeClient, + closer io.Closer, + err error, +) + +// newV1NodeClient creates a new NodeClient with the internally used gRPC +// connection set up. It also returns a closer which must be called to close +// the gRPC connection when the NodeClient is not used anymore. +// This is the default implementation for the nodeV1ClientCreator, used in +// newDRAPluginClient. +func newV1NodeClient(addr draAddr) (nodeClient drapbv1.NodeClient, closer io.Closer, err error) { + var conn *grpc.ClientConn + + conn, err = newGrpcConn(addr) + if err != nil { + return nil, nil, err + } + + return drapbv1.NewNodeClient(conn), conn, nil +} + +func NewDRAPluginClient(pluginName string) (Client, error) { + if pluginName == "" { + return nil, fmt.Errorf("plugin name is empty") + } + + existingPlugin := draPlugins.Get(pluginName) + if existingPlugin == nil { + return nil, fmt.Errorf("plugin name %s not found in the list of registered DRA plugins", pluginName) + } + + return &draPluginClient{ + pluginName: pluginName, + addr: draAddr(existingPlugin.endpoint), + nodeV1ClientCreator: newV1NodeClient, + }, nil +} + +func (r *draPluginClient) NodePrepareResource( + ctx context.Context, + namespace string, + claimUID types.UID, + claimName string, + resourceHandle string, +) (*drapbv1.NodePrepareResourceResponse, error) { + klog.V(4).InfoS( + log("calling NodePrepareResource rpc"), + "namespace", namespace, + "claim UID", claimUID, + "claim name", claimName, + "resource handle", resourceHandle) + + if r.nodeV1ClientCreator == nil { + return nil, errors.New("failed to call NodePrepareResource. nodeV1ClientCreator is nil") + } + + nodeClient, closer, err := r.nodeV1ClientCreator(r.addr) + if err != nil { + return nil, err + } + defer closer.Close() + + req := &drapbv1.NodePrepareResourceRequest{ + Namespace: namespace, + ClaimUid: string(claimUID), + ClaimName: claimName, + ResourceHandle: resourceHandle, + } + + return nodeClient.NodePrepareResource(ctx, req) +} + +func (r *draPluginClient) NodeUnprepareResource( + ctx context.Context, + namespace string, + claimUID types.UID, + claimName string, + cdiDevices []string, +) (*drapbv1.NodeUnprepareResourceResponse, error) { + klog.V(4).InfoS( + log("calling NodeUnprepareResource rpc"), + "namespace", namespace, + "claim UID", claimUID, + "claim name", claimName, + "cdi devices", cdiDevices) + + if r.nodeV1ClientCreator == nil { + return nil, errors.New("nodeV1ClientCreate is nil") + } + + nodeClient, closer, err := r.nodeV1ClientCreator(r.addr) + if err != nil { + return nil, err + } + defer closer.Close() + + req := &drapbv1.NodeUnprepareResourceRequest{ + Namespace: namespace, + ClaimUid: string(claimUID), + ClaimName: claimName, + CdiDevices: cdiDevices, + } + + return nodeClient.NodeUnprepareResource(ctx, req) +} + +func newGrpcConn(addr draAddr) (*grpc.ClientConn, error) { + network := "unix" + klog.V(4).InfoS(log("creating new gRPC connection"), "protocol", network, "endpoint", addr) + + return grpc.Dial( + string(addr), + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithContextDialer(func(ctx context.Context, target string) (net.Conn, error) { + return (&net.Dialer{}).DialContext(ctx, network, target) + }), + ) +} diff --git a/pkg/kubelet/cm/dra/plugin/plugin.go b/pkg/kubelet/cm/dra/plugin/plugin.go new file mode 100644 index 00000000000..0f2a1ff4cb4 --- /dev/null +++ b/pkg/kubelet/cm/dra/plugin/plugin.go @@ -0,0 +1,178 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package plugin + +import ( + "errors" + "fmt" + "strings" + + utilversion "k8s.io/apimachinery/pkg/util/version" + "k8s.io/klog/v2" +) + +const ( + // DRAPluginName is the name of the in-tree DRA Plugin. + DRAPluginName = "kubernetes.io/dra" +) + +// draPlugins map keeps track of all registered DRA plugins on the node +// and their corresponding sockets. +var draPlugins = &PluginsStore{} + +// RegistrationHandler is the handler which is fed to the pluginwatcher API. +type RegistrationHandler struct{} + +// NewPluginHandler returns new registration handler. +func NewRegistrationHandler() *RegistrationHandler { + return &RegistrationHandler{} +} + +// RegisterPlugin is called when a plugin can be registered. +func (h *RegistrationHandler) RegisterPlugin(pluginName string, endpoint string, versions []string) error { + klog.InfoS("Register new DRA plugin", "name", pluginName, "endpoint", endpoint) + + highestSupportedVersion, err := h.validateVersions("RegisterPlugin", pluginName, versions) + if err != nil { + return err + } + + // Storing endpoint of newly registered DRA Plugin into the map, where plugin name will be the key + // all other DRA components will be able to get the actual socket of DRA plugins by its name. + draPlugins.Set(pluginName, &Plugin{ + endpoint: endpoint, + highestSupportedVersion: highestSupportedVersion, + }) + + return nil +} + +// Return the highest supported version. +func highestSupportedVersion(versions []string) (*utilversion.Version, error) { + if len(versions) == 0 { + return nil, errors.New(log("DRA plugin reporting empty array for supported versions")) + } + + var highestSupportedVersion *utilversion.Version + + var theErr error + + for i := len(versions) - 1; i >= 0; i-- { + currentHighestVer, err := utilversion.ParseGeneric(versions[i]) + if err != nil { + theErr = err + + continue + } + + if currentHighestVer.Major() > 1 { + // DRA currently only has version 1.x + continue + } + + if highestSupportedVersion == nil || highestSupportedVersion.LessThan(currentHighestVer) { + highestSupportedVersion = currentHighestVer + } + } + + if highestSupportedVersion == nil { + return nil, fmt.Errorf( + "could not find a highest supported version from versions (%v) reported by this plugin: %+v", + versions, theErr) + } + + if highestSupportedVersion.Major() != 1 { + return nil, fmt.Errorf("highest supported version reported by plugin is %v, must be v1.x", highestSupportedVersion) + } + + return highestSupportedVersion, nil +} + +func (h *RegistrationHandler) validateVersions( + callerName string, + pluginName string, + versions []string, +) (*utilversion.Version, error) { + if len(versions) == 0 { + return nil, errors.New( + log( + "%s for DRA plugin %q failed. Plugin returned an empty list for supported versions", + callerName, + pluginName, + ), + ) + } + + // Validate version + newPluginHighestVersion, err := highestSupportedVersion(versions) + if err != nil { + return nil, errors.New( + log( + "%s for DRA plugin %q failed. None of the versions specified %q are supported. err=%v", + callerName, + pluginName, + versions, + err, + ), + ) + } + + existingPlugin := draPlugins.Get(pluginName) + if existingPlugin != nil { + if !existingPlugin.highestSupportedVersion.LessThan(newPluginHighestVersion) { + return nil, errors.New( + log( + "%s for DRA plugin %q failed. Another plugin with the same name is already registered with a higher supported version: %q", + callerName, + pluginName, + existingPlugin.highestSupportedVersion, + ), + ) + } + } + + return newPluginHighestVersion, nil +} + +func unregisterPlugin(pluginName string) { + draPlugins.Delete(pluginName) +} + +// DeRegisterPlugin is called when a plugin has removed its socket, +// signaling it is no longer available. +func (h *RegistrationHandler) DeRegisterPlugin(pluginName string) { + klog.InfoS("DeRegister DRA plugin", "name", pluginName) + unregisterPlugin(pluginName) +} + +// ValidatePlugin is called by kubelet's plugin watcher upon detection +// of a new registration socket opened by DRA plugin. +func (h *RegistrationHandler) ValidatePlugin(pluginName string, endpoint string, versions []string) error { + klog.InfoS("Validate DRA plugin", "name", pluginName, "endpoint", endpoint, "versions", strings.Join(versions, ",")) + + _, err := h.validateVersions("ValidatePlugin", pluginName, versions) + if err != nil { + return fmt.Errorf("validation failed for DRA plugin %s at endpoint %s: %+v", pluginName, endpoint, err) + } + + return err +} + +// log prepends log string with `kubernetes.io/dra`. +func log(msg string, parts ...interface{}) string { + return fmt.Sprintf(fmt.Sprintf("%s: %s", DRAPluginName, msg), parts...) +} diff --git a/pkg/kubelet/cm/dra/plugin/plugins_store.go b/pkg/kubelet/cm/dra/plugin/plugins_store.go new file mode 100644 index 00000000000..90adb702ac7 --- /dev/null +++ b/pkg/kubelet/cm/dra/plugin/plugins_store.go @@ -0,0 +1,76 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package plugin + +import ( + "sync" + + utilversion "k8s.io/apimachinery/pkg/util/version" +) + +// Plugin is a description of a DRA Plugin, defined by an endpoint +// and the highest DRA version supported. +type Plugin struct { + endpoint string + highestSupportedVersion *utilversion.Version +} + +// PluginsStore holds a list of DRA Plugins. +type PluginsStore struct { + sync.RWMutex + store map[string]*Plugin +} + +// Get lets you retrieve a DRA Plugin by name. +// This method is protected by a mutex. +func (s *PluginsStore) Get(pluginName string) *Plugin { + s.RLock() + defer s.RUnlock() + + return s.store[pluginName] +} + +// Set lets you save a DRA Plugin to the list and give it a specific name. +// This method is protected by a mutex. +func (s *PluginsStore) Set(pluginName string, plugin *Plugin) { + s.Lock() + defer s.Unlock() + + if s.store == nil { + s.store = make(map[string]*Plugin) + } + + s.store[pluginName] = plugin +} + +// Delete lets you delete a DRA Plugin by name. +// This method is protected by a mutex. +func (s *PluginsStore) Delete(pluginName string) { + s.Lock() + defer s.Unlock() + + delete(s.store, pluginName) +} + +// Clear deletes all entries in the store. +// This methiod is protected by a mutex. +func (s *PluginsStore) Clear() { + s.Lock() + defer s.Unlock() + + s.store = make(map[string]*Plugin) +} diff --git a/pkg/kubelet/cm/dra/types.go b/pkg/kubelet/cm/dra/types.go new file mode 100644 index 00000000000..894b2f30507 --- /dev/null +++ b/pkg/kubelet/cm/dra/types.go @@ -0,0 +1,44 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dra + +import ( + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" +) + +// Manager manages all the DRA resource plugins running on a node. +type Manager interface { + // PrepareResources prepares resources for a container in a pod. + // It communicates with the DRA resource plugin to prepare resources and + // returns resource info to trigger CDI injection by the runtime. + PrepareResources(pod *v1.Pod, container *v1.Container) (*ContainerInfo, error) + + // UnprepareResources calls NodeUnprepareResource GRPC from DRA plugin to unprepare pod resources + UnprepareResources(pod *v1.Pod) error + + // PodMightNeedToUnprepareResources returns true if the pod with the given UID + // might need to unprepare resources. + PodMightNeedToUnprepareResources(UID types.UID) bool +} + +// ContainerInfo contains information required by the runtime to consume prepared resources. +type ContainerInfo struct { + // The Annotations for the container + Annotations []kubecontainer.Annotation +} diff --git a/pkg/kubelet/cm/fake_container_manager.go b/pkg/kubelet/cm/fake_container_manager.go index 685246276c5..3c3be7bed50 100644 --- a/pkg/kubelet/cm/fake_container_manager.go +++ b/pkg/kubelet/cm/fake_container_manager.go @@ -22,9 +22,11 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/types" internalapi "k8s.io/cri-api/pkg/apis" podresourcesapi "k8s.io/kubelet/pkg/apis/podresources/v1" "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager" + "k8s.io/kubernetes/pkg/kubelet/cm/dra" "k8s.io/kubernetes/pkg/kubelet/cm/memorymanager" "k8s.io/kubernetes/pkg/kubelet/cm/topologymanager" "k8s.io/kubernetes/pkg/kubelet/config" @@ -236,3 +238,15 @@ func (cm *FakeContainerManager) GetNodeAllocatableAbsolute() v1.ResourceList { defer cm.Unlock() return nil } + +func (cm *FakeContainerManager) PrepareResources(pod *v1.Pod, container *v1.Container) (*dra.ContainerInfo, error) { + return nil, nil +} + +func (cm *FakeContainerManager) UnprepareResources(*v1.Pod) error { + return nil +} + +func (cm *FakeContainerManager) PodMightNeedToUnprepareResources(UID types.UID) bool { + return false +} diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 1a3916a3faa..1a03b11ed46 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -72,6 +72,7 @@ import ( kubeletcertificate "k8s.io/kubernetes/pkg/kubelet/certificate" "k8s.io/kubernetes/pkg/kubelet/cloudresource" "k8s.io/kubernetes/pkg/kubelet/cm" + draplugin "k8s.io/kubernetes/pkg/kubelet/cm/dra/plugin" "k8s.io/kubernetes/pkg/kubelet/config" "k8s.io/kubernetes/pkg/kubelet/configmap" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" @@ -1473,8 +1474,13 @@ func (kl *Kubelet) initializeRuntimeDependentModules() { kl.containerLogManager.Start() // Adding Registration Callback function for CSI Driver kl.pluginManager.AddHandler(pluginwatcherapi.CSIPlugin, plugincache.PluginHandler(csi.PluginHandler)) + // Adding Registration Callback function for DRA Plugin + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) { + kl.pluginManager.AddHandler(pluginwatcherapi.DRAPlugin, plugincache.PluginHandler(draplugin.NewRegistrationHandler())) + } // Adding Registration Callback function for Device Manager kl.pluginManager.AddHandler(pluginwatcherapi.DevicePlugin, kl.containerManager.GetPluginRegistrationHandler()) + // Start the plugin manager klog.V(4).InfoS("Starting plugin manager") go kl.pluginManager.Run(kl.sourcesReady, wait.NeverStop) @@ -1936,6 +1942,15 @@ func (kl *Kubelet) syncTerminatingPod(_ context.Context, pod *v1.Pod, podStatus return fmt.Errorf("detected running containers after a successful KillPod, CRI violation: %v", runningContainers) } + // NOTE: resources must be unprepared AFTER all containers have stopped + // and BEFORE the pod status is changed on the API server + // to avoid race conditions with the resource deallocation code in kubernetes core. + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) { + if err := kl.containerManager.UnprepareResources(pod); err != nil { + return err + } + } + // we have successfully stopped all containers, the pod is terminating, our status is "done" klog.V(4).InfoS("Pod termination stopped all running containers", "pod", klog.KObj(pod), "podUID", pod.UID) @@ -1953,6 +1968,7 @@ func (kl *Kubelet) syncTerminatedPod(ctx context.Context, pod *v1.Pod, podStatus // generate the final status of the pod // TODO: should we simply fold this into TerminatePod? that would give a single pod update apiPodStatus := kl.generateAPIPodStatus(pod, podStatus) + kl.statusManager.SetPodStatus(pod, apiPodStatus) // volumes are unmounted after the pod worker reports ShouldPodRuntimeBeRemoved (which is satisfied diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index 881492a1506..2e309de82c8 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -927,7 +927,21 @@ func countRunningContainerStatus(status v1.PodStatus) int { // PodCouldHaveRunningContainers returns true if the pod with the given UID could still have running // containers. This returns false if the pod has not yet been started or the pod is unknown. func (kl *Kubelet) PodCouldHaveRunningContainers(pod *v1.Pod) bool { - return kl.podWorkers.CouldHaveRunningContainers(pod.UID) + if kl.podWorkers.CouldHaveRunningContainers(pod.UID) { + return true + } + + // Check if pod might need to unprepare resources before termination + // NOTE: This is a temporary solution. This call is here to avoid changing + // status manager and its tests. + // TODO: extend PodDeletionSafetyProvider interface and implement it + // in a separate Kubelet method. + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) { + if kl.containerManager.PodMightNeedToUnprepareResources(pod.UID) { + return true + } + } + return false } // PodResourcesAreReclaimed returns true if all required node-level resources that a pod was consuming have diff --git a/pkg/printers/internalversion/import_known_versions.go b/pkg/printers/internalversion/import_known_versions.go index 027e89fe1aa..c9c2674475e 100644 --- a/pkg/printers/internalversion/import_known_versions.go +++ b/pkg/printers/internalversion/import_known_versions.go @@ -32,6 +32,7 @@ import ( _ "k8s.io/kubernetes/pkg/apis/extensions/install" _ "k8s.io/kubernetes/pkg/apis/policy/install" _ "k8s.io/kubernetes/pkg/apis/rbac/install" + _ "k8s.io/kubernetes/pkg/apis/resource/install" _ "k8s.io/kubernetes/pkg/apis/scheduling/install" _ "k8s.io/kubernetes/pkg/apis/storage/install" ) diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index 69c7200cf95..13adc816120 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -40,6 +40,7 @@ import ( networkingv1alpha1 "k8s.io/api/networking/v1alpha1" policyv1beta1 "k8s.io/api/policy/v1beta1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" schedulingv1 "k8s.io/api/scheduling/v1" storagev1 "k8s.io/api/storage/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -65,6 +66,7 @@ import ( nodeapi "k8s.io/kubernetes/pkg/apis/node" "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/rbac" + "k8s.io/kubernetes/pkg/apis/resource" "k8s.io/kubernetes/pkg/apis/scheduling" "k8s.io/kubernetes/pkg/apis/storage" storageutil "k8s.io/kubernetes/pkg/apis/storage/util" @@ -622,6 +624,41 @@ func AddHandlers(h printers.PrintHandler) { h.TableHandler(clusterCIDRColumnDefinitions, printClusterCIDR) h.TableHandler(clusterCIDRColumnDefinitions, printClusterCIDRList) + + resourceClassColumnDefinitions := []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, + {Name: "DriverName", Type: "string", Description: resourcev1alpha1.ResourceClass{}.SwaggerDoc()["driverName"]}, + {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, + } + _ = h.TableHandler(resourceClassColumnDefinitions, printResourceClass) + _ = h.TableHandler(resourceClassColumnDefinitions, printResourceClassList) + + resourceClaimColumnDefinitions := []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, + {Name: "ResourceClassName", Type: "string", Description: resourcev1alpha1.ResourceClaimSpec{}.SwaggerDoc()["resourceClassName"]}, + {Name: "AllocationMode", Type: "string", Description: resourcev1alpha1.ResourceClaimSpec{}.SwaggerDoc()["allocationMode"]}, + {Name: "State", Type: "string", Description: "A summary of the current state (allocated, pending, reserved, etc.)."}, + {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, + } + _ = h.TableHandler(resourceClaimColumnDefinitions, printResourceClaim) + _ = h.TableHandler(resourceClaimColumnDefinitions, printResourceClaimList) + + resourceClaimTemplateColumnDefinitions := []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, + {Name: "ResourceClassName", Type: "string", Description: resourcev1alpha1.ResourceClaimSpec{}.SwaggerDoc()["resourceClassName"]}, + {Name: "AllocationMode", Type: "string", Description: resourcev1alpha1.ResourceClaimSpec{}.SwaggerDoc()["allocationMode"]}, + {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, + } + _ = h.TableHandler(resourceClaimTemplateColumnDefinitions, printResourceClaimTemplate) + _ = h.TableHandler(resourceClaimTemplateColumnDefinitions, printResourceClaimTemplateList) + + podSchedulingColumnDefinitions := []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, + {Name: "SelectedNode", Type: "string", Description: resourcev1alpha1.PodSchedulingSpec{}.SwaggerDoc()["selectedNode"]}, + {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, + } + _ = h.TableHandler(podSchedulingColumnDefinitions, printPodScheduling) + _ = h.TableHandler(podSchedulingColumnDefinitions, printPodSchedulingList) } // Pass ports=nil for all ports. @@ -2797,6 +2834,110 @@ func printScale(obj *autoscaling.Scale, options printers.GenerateOptions) ([]met return []metav1.TableRow{row}, nil } +func printResourceClass(obj *resource.ResourceClass, options printers.GenerateOptions) ([]metav1.TableRow, error) { + row := metav1.TableRow{ + Object: runtime.RawExtension{Object: obj}, + } + row.Cells = append(row.Cells, obj.Name, obj.DriverName, translateTimestampSince(obj.CreationTimestamp)) + + return []metav1.TableRow{row}, nil +} + +func printResourceClassList(list *resource.ResourceClassList, options printers.GenerateOptions) ([]metav1.TableRow, error) { + rows := make([]metav1.TableRow, 0, len(list.Items)) + for i := range list.Items { + r, err := printResourceClass(&list.Items[i], options) + if err != nil { + return nil, err + } + rows = append(rows, r...) + } + return rows, nil +} + +func printResourceClaim(obj *resource.ResourceClaim, options printers.GenerateOptions) ([]metav1.TableRow, error) { + row := metav1.TableRow{ + Object: runtime.RawExtension{Object: obj}, + } + row.Cells = append(row.Cells, obj.Name, obj.Spec.ResourceClassName, string(obj.Spec.AllocationMode), resourceClaimState(obj), translateTimestampSince(obj.CreationTimestamp)) + + return []metav1.TableRow{row}, nil +} + +func resourceClaimState(obj *resource.ResourceClaim) string { + var states []string + if obj.DeletionTimestamp != nil { + states = append(states, "deleted") + } + if obj.Status.Allocation == nil { + if obj.DeletionTimestamp == nil { + states = append(states, "pending") + } + } else { + states = append(states, "allocated") + if len(obj.Status.ReservedFor) > 0 { + states = append(states, "reserved") + } else if obj.DeletionTimestamp != nil || obj.Status.DeallocationRequested { + states = append(states, "deallocating") + } + } + return strings.Join(states, ",") +} + +func printResourceClaimList(list *resource.ResourceClaimList, options printers.GenerateOptions) ([]metav1.TableRow, error) { + rows := make([]metav1.TableRow, 0, len(list.Items)) + for i := range list.Items { + r, err := printResourceClaim(&list.Items[i], options) + if err != nil { + return nil, err + } + rows = append(rows, r...) + } + return rows, nil +} + +func printResourceClaimTemplate(obj *resource.ResourceClaimTemplate, options printers.GenerateOptions) ([]metav1.TableRow, error) { + row := metav1.TableRow{ + Object: runtime.RawExtension{Object: obj}, + } + row.Cells = append(row.Cells, obj.Name, obj.Spec.Spec.ResourceClassName, string(obj.Spec.Spec.AllocationMode), translateTimestampSince(obj.CreationTimestamp)) + + return []metav1.TableRow{row}, nil +} + +func printResourceClaimTemplateList(list *resource.ResourceClaimTemplateList, options printers.GenerateOptions) ([]metav1.TableRow, error) { + rows := make([]metav1.TableRow, 0, len(list.Items)) + for i := range list.Items { + r, err := printResourceClaimTemplate(&list.Items[i], options) + if err != nil { + return nil, err + } + rows = append(rows, r...) + } + return rows, nil +} + +func printPodScheduling(obj *resource.PodScheduling, options printers.GenerateOptions) ([]metav1.TableRow, error) { + row := metav1.TableRow{ + Object: runtime.RawExtension{Object: obj}, + } + row.Cells = append(row.Cells, obj.Name, obj.Spec.SelectedNode, translateTimestampSince(obj.CreationTimestamp)) + + return []metav1.TableRow{row}, nil +} + +func printPodSchedulingList(list *resource.PodSchedulingList, options printers.GenerateOptions) ([]metav1.TableRow, error) { + rows := make([]metav1.TableRow, 0, len(list.Items)) + for i := range list.Items { + r, err := printPodScheduling(&list.Items[i], options) + if err != nil { + return nil, err + } + rows = append(rows, r...) + } + return rows, nil +} + func printBoolPtr(value *bool) string { if value != nil { return printBool(*value) diff --git a/pkg/registry/resource/OWNERS b/pkg/registry/resource/OWNERS new file mode 100644 index 00000000000..98397072ae5 --- /dev/null +++ b/pkg/registry/resource/OWNERS @@ -0,0 +1,6 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +reviewers: + - bart0sh + - klueska + - pohly diff --git a/pkg/registry/resource/podscheduling/storage/storage.go b/pkg/registry/resource/podscheduling/storage/storage.go new file mode 100644 index 00000000000..b977f283b85 --- /dev/null +++ b/pkg/registry/resource/podscheduling/storage/storage.go @@ -0,0 +1,100 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package storage + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/registry/generic" + genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" + "k8s.io/apiserver/pkg/registry/rest" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/kubernetes/pkg/printers" + printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" + printerstorage "k8s.io/kubernetes/pkg/printers/storage" + "k8s.io/kubernetes/pkg/registry/resource/podscheduling" + "sigs.k8s.io/structured-merge-diff/v4/fieldpath" +) + +// REST implements a RESTStorage for PodSchedulings. +type REST struct { + *genericregistry.Store +} + +// NewREST returns a RESTStorage object that will work against PodSchedulings. +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { + store := &genericregistry.Store{ + NewFunc: func() runtime.Object { return &resource.PodScheduling{} }, + NewListFunc: func() runtime.Object { return &resource.PodSchedulingList{} }, + PredicateFunc: podscheduling.Match, + DefaultQualifiedResource: resource.Resource("podschedulings"), + + CreateStrategy: podscheduling.Strategy, + UpdateStrategy: podscheduling.Strategy, + DeleteStrategy: podscheduling.Strategy, + ReturnDeletedObject: true, + ResetFieldsStrategy: podscheduling.Strategy, + + TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)}, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: podscheduling.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + return nil, nil, err + } + + statusStore := *store + statusStore.UpdateStrategy = podscheduling.StatusStrategy + statusStore.ResetFieldsStrategy = podscheduling.StatusStrategy + + rest := &REST{store} + + return rest, &StatusREST{store: &statusStore}, nil +} + +// StatusREST implements the REST endpoint for changing the status of a PodScheduling. +type StatusREST struct { + store *genericregistry.Store +} + +// New creates a new PodScheduling object. +func (r *StatusREST) New() runtime.Object { + return &resource.PodScheduling{} +} + +func (r *StatusREST) Destroy() { + // Given that underlying store is shared with REST, + // we don't destroy it here explicitly. +} + +// Get retrieves the object from the storage. It is required to support Patch. +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { + return r.store.Get(ctx, name, options) +} + +// Update alters the status subset of an object. +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) { + // We are explicitly setting forceAllowCreate to false in the call to the underlying storage because + // subresources should never allow create on update. + return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options) +} + +// GetResetFields implements rest.ResetFieldsStrategy +func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { + return r.store.GetResetFields() +} diff --git a/pkg/registry/resource/podscheduling/storage/storage_test.go b/pkg/registry/resource/podscheduling/storage/storage_test.go new file mode 100644 index 00000000000..b400a2abcbc --- /dev/null +++ b/pkg/registry/resource/podscheduling/storage/storage_test.go @@ -0,0 +1,184 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package storage + +import ( + "testing" + + apiequality "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/diff" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/apiserver/pkg/registry/generic" + genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing" + "k8s.io/apiserver/pkg/registry/rest" + etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing" + "k8s.io/kubernetes/pkg/apis/resource" + _ "k8s.io/kubernetes/pkg/apis/resource/install" + "k8s.io/kubernetes/pkg/registry/registrytest" +) + +func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer) { + etcdStorage, server := registrytest.NewEtcdStorage(t, resource.GroupName) + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "podschedulings", + } + podSchedulingStorage, statusStorage, err := NewREST(restOptions) + if err != nil { + t.Fatalf("unexpected error from REST storage: %v", err) + } + return podSchedulingStorage, statusStorage, server +} + +func validNewPodScheduling(name, ns string) *resource.PodScheduling { + scheduling := &resource.PodScheduling{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: ns, + }, + Spec: resource.PodSchedulingSpec{ + SelectedNode: "worker", + }, + Status: resource.PodSchedulingStatus{}, + } + return scheduling +} + +func TestCreate(t *testing.T) { + storage, _, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + scheduling := validNewPodScheduling("foo", metav1.NamespaceDefault) + scheduling.ObjectMeta = metav1.ObjectMeta{} + test.TestCreate( + // valid + scheduling, + // invalid + &resource.PodScheduling{ + ObjectMeta: metav1.ObjectMeta{Name: "*BadName!"}, + }, + ) +} + +func TestUpdate(t *testing.T) { + storage, _, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + test.TestUpdate( + // valid + validNewPodScheduling("foo", metav1.NamespaceDefault), + // updateFunc + func(obj runtime.Object) runtime.Object { + object := obj.(*resource.PodScheduling) + if object.Labels == nil { + object.Labels = map[string]string{} + } + object.Labels["foo"] = "bar" + return object + }, + ) +} + +func TestDelete(t *testing.T) { + storage, _, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store).ReturnDeletedObject() + test.TestDelete(validNewPodScheduling("foo", metav1.NamespaceDefault)) +} + +func TestGet(t *testing.T) { + storage, _, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + test.TestGet(validNewPodScheduling("foo", metav1.NamespaceDefault)) +} + +func TestList(t *testing.T) { + storage, _, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + test.TestList(validNewPodScheduling("foo", metav1.NamespaceDefault)) +} + +func TestWatch(t *testing.T) { + storage, _, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + test.TestWatch( + validNewPodScheduling("foo", metav1.NamespaceDefault), + // matching labels + []labels.Set{}, + // not matching labels + []labels.Set{ + {"foo": "bar"}, + }, + // matching fields + []fields.Set{ + {"metadata.name": "foo"}, + }, + // not matching fields + []fields.Set{ + {"metadata.name": "bar"}, + }, + ) +} + +func TestUpdateStatus(t *testing.T) { + storage, statusStorage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + ctx := genericapirequest.NewDefaultContext() + + key, _ := storage.KeyFunc(ctx, "foo") + schedulingStart := validNewPodScheduling("foo", metav1.NamespaceDefault) + err := storage.Storage.Create(ctx, key, schedulingStart, nil, 0, false) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + scheduling := schedulingStart.DeepCopy() + scheduling.Status.ResourceClaims = append(scheduling.Status.ResourceClaims, + resource.ResourceClaimSchedulingStatus{ + Name: "my-claim", + }, + ) + _, _, err = statusStorage.Update(ctx, scheduling.Name, rest.DefaultUpdatedObjectInfo(scheduling), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + obj, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + schedulingOut := obj.(*resource.PodScheduling) + // only compare relevant changes b/c of difference in metadata + if !apiequality.Semantic.DeepEqual(scheduling.Status, schedulingOut.Status) { + t.Errorf("unexpected object: %s", diff.ObjectDiff(scheduling.Status, schedulingOut.Status)) + } +} diff --git a/pkg/registry/resource/podscheduling/strategy.go b/pkg/registry/resource/podscheduling/strategy.go new file mode 100644 index 00000000000..99421213f4c --- /dev/null +++ b/pkg/registry/resource/podscheduling/strategy.go @@ -0,0 +1,163 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package podscheduling + +import ( + "context" + "errors" + + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/apiserver/pkg/registry/generic" + "k8s.io/apiserver/pkg/storage" + "k8s.io/apiserver/pkg/storage/names" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/kubernetes/pkg/apis/resource/validation" + "sigs.k8s.io/structured-merge-diff/v4/fieldpath" +) + +// podSchedulingStrategy implements behavior for PodScheduling objects +type podSchedulingStrategy struct { + runtime.ObjectTyper + names.NameGenerator +} + +// Strategy is the default logic that applies when creating and updating +// ResourceClaim objects via the REST API. +var Strategy = podSchedulingStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} + +func (podSchedulingStrategy) NamespaceScoped() bool { + return true +} + +// GetResetFields returns the set of fields that get reset by the strategy and +// should not be modified by the user. For a new PodScheduling that is the +// status. +func (podSchedulingStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { + fields := map[fieldpath.APIVersion]*fieldpath.Set{ + "resource.k8s.io/v1alpha1": fieldpath.NewSet( + fieldpath.MakePathOrDie("status"), + ), + } + + return fields +} + +func (podSchedulingStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { + scheduling := obj.(*resource.PodScheduling) + // Status must not be set by user on create. + scheduling.Status = resource.PodSchedulingStatus{} +} + +func (podSchedulingStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { + scheduling := obj.(*resource.PodScheduling) + return validation.ValidatePodScheduling(scheduling) +} + +func (podSchedulingStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string { + return nil +} + +func (podSchedulingStrategy) Canonicalize(obj runtime.Object) { +} + +func (podSchedulingStrategy) AllowCreateOnUpdate() bool { + return false +} + +func (podSchedulingStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { + newScheduling := obj.(*resource.PodScheduling) + oldScheduling := old.(*resource.PodScheduling) + newScheduling.Status = oldScheduling.Status +} + +func (podSchedulingStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { + newScheduling := obj.(*resource.PodScheduling) + oldScheduling := old.(*resource.PodScheduling) + errorList := validation.ValidatePodScheduling(newScheduling) + return append(errorList, validation.ValidatePodSchedulingUpdate(newScheduling, oldScheduling)...) +} + +func (podSchedulingStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { + return nil +} + +func (podSchedulingStrategy) AllowUnconditionalUpdate() bool { + return true +} + +type podSchedulingStatusStrategy struct { + podSchedulingStrategy +} + +var StatusStrategy = podSchedulingStatusStrategy{Strategy} + +// GetResetFields returns the set of fields that get reset by the strategy and +// should not be modified by the user. For a status update that is the spec. +func (podSchedulingStatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { + fields := map[fieldpath.APIVersion]*fieldpath.Set{ + "resource.k8s.io/v1alpha1": fieldpath.NewSet( + fieldpath.MakePathOrDie("spec"), + ), + } + + return fields +} + +func (podSchedulingStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { + newScheduling := obj.(*resource.PodScheduling) + oldScheduling := old.(*resource.PodScheduling) + newScheduling.Spec = oldScheduling.Spec +} + +func (podSchedulingStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { + newScheduling := obj.(*resource.PodScheduling) + oldScheduling := old.(*resource.PodScheduling) + return validation.ValidatePodSchedulingStatusUpdate(newScheduling, oldScheduling) +} + +// WarningsOnUpdate returns warnings for the given update. +func (podSchedulingStatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { + return nil +} + +// Match returns a generic matcher for a given label and field selector. +func Match(label labels.Selector, field fields.Selector) storage.SelectionPredicate { + return storage.SelectionPredicate{ + Label: label, + Field: field, + GetAttrs: GetAttrs, + } +} + +// GetAttrs returns labels and fields of a given object for filtering purposes. +func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { + scheduling, ok := obj.(*resource.PodScheduling) + if !ok { + return nil, nil, errors.New("not a PodScheduling") + } + return labels.Set(scheduling.Labels), toSelectableFields(scheduling), nil +} + +// toSelectableFields returns a field set that represents the object +func toSelectableFields(scheduling *resource.PodScheduling) fields.Set { + fields := generic.ObjectMetaFieldsSet(&scheduling.ObjectMeta, true) + return fields +} diff --git a/pkg/registry/resource/podscheduling/strategy_test.go b/pkg/registry/resource/podscheduling/strategy_test.go new file mode 100644 index 00000000000..9ad878c68ac --- /dev/null +++ b/pkg/registry/resource/podscheduling/strategy_test.go @@ -0,0 +1,84 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package podscheduling + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/kubernetes/pkg/apis/resource" +) + +var podScheduling = &resource.PodScheduling{ + ObjectMeta: metav1.ObjectMeta{ + Name: "valid-pod", + Namespace: "default", + }, + Spec: resource.PodSchedulingSpec{ + SelectedNode: "worker", + }, +} + +func TestPodSchedulingStrategy(t *testing.T) { + if !Strategy.NamespaceScoped() { + t.Errorf("PodScheduling must be namespace scoped") + } + if Strategy.AllowCreateOnUpdate() { + t.Errorf("PodScheduling should not allow create on update") + } +} + +func TestPodSchedulingStrategyCreate(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() + podScheduling := podScheduling.DeepCopy() + + Strategy.PrepareForCreate(ctx, podScheduling) + errs := Strategy.Validate(ctx, podScheduling) + if len(errs) != 0 { + t.Errorf("unexpected error validating for create %v", errs) + } +} + +func TestPodSchedulingStrategyUpdate(t *testing.T) { + t.Run("no-changes-okay", func(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() + podScheduling := podScheduling.DeepCopy() + newPodScheduling := podScheduling.DeepCopy() + newPodScheduling.ResourceVersion = "4" + + Strategy.PrepareForUpdate(ctx, newPodScheduling, podScheduling) + errs := Strategy.ValidateUpdate(ctx, newPodScheduling, podScheduling) + if len(errs) != 0 { + t.Errorf("unexpected validation errors: %v", errs) + } + }) + + t.Run("name-change-not-allowed", func(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() + podScheduling := podScheduling.DeepCopy() + newPodScheduling := podScheduling.DeepCopy() + newPodScheduling.Name = "valid-claim-2" + newPodScheduling.ResourceVersion = "4" + + Strategy.PrepareForUpdate(ctx, newPodScheduling, podScheduling) + errs := Strategy.ValidateUpdate(ctx, newPodScheduling, podScheduling) + if len(errs) == 0 { + t.Errorf("expected a validation error") + } + }) +} diff --git a/pkg/registry/resource/resourceclaim/storage/storage.go b/pkg/registry/resource/resourceclaim/storage/storage.go new file mode 100644 index 00000000000..959cb680bfe --- /dev/null +++ b/pkg/registry/resource/resourceclaim/storage/storage.go @@ -0,0 +1,100 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package storage + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/registry/generic" + genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" + "k8s.io/apiserver/pkg/registry/rest" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/kubernetes/pkg/printers" + printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" + printerstorage "k8s.io/kubernetes/pkg/printers/storage" + "k8s.io/kubernetes/pkg/registry/resource/resourceclaim" + "sigs.k8s.io/structured-merge-diff/v4/fieldpath" +) + +// REST implements a RESTStorage for ResourceClaims. +type REST struct { + *genericregistry.Store +} + +// NewREST returns a RESTStorage object that will work against ResourceClaims. +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) { + store := &genericregistry.Store{ + NewFunc: func() runtime.Object { return &resource.ResourceClaim{} }, + NewListFunc: func() runtime.Object { return &resource.ResourceClaimList{} }, + PredicateFunc: resourceclaim.Match, + DefaultQualifiedResource: resource.Resource("resourceclaims"), + + CreateStrategy: resourceclaim.Strategy, + UpdateStrategy: resourceclaim.Strategy, + DeleteStrategy: resourceclaim.Strategy, + ReturnDeletedObject: true, + ResetFieldsStrategy: resourceclaim.Strategy, + + TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)}, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: resourceclaim.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + return nil, nil, err + } + + statusStore := *store + statusStore.UpdateStrategy = resourceclaim.StatusStrategy + statusStore.ResetFieldsStrategy = resourceclaim.StatusStrategy + + rest := &REST{store} + + return rest, &StatusREST{store: &statusStore}, nil +} + +// StatusREST implements the REST endpoint for changing the status of a ResourceClaim. +type StatusREST struct { + store *genericregistry.Store +} + +// New creates a new ResourceClaim object. +func (r *StatusREST) New() runtime.Object { + return &resource.ResourceClaim{} +} + +func (r *StatusREST) Destroy() { + // Given that underlying store is shared with REST, + // we don't destroy it here explicitly. +} + +// Get retrieves the object from the storage. It is required to support Patch. +func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { + return r.store.Get(ctx, name, options) +} + +// Update alters the status subset of an object. +func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) { + // We are explicitly setting forceAllowCreate to false in the call to the underlying storage because + // subresources should never allow create on update. + return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options) +} + +// GetResetFields implements rest.ResetFieldsStrategy +func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { + return r.store.GetResetFields() +} diff --git a/pkg/registry/resource/resourceclaim/storage/storage_test.go b/pkg/registry/resource/resourceclaim/storage/storage_test.go new file mode 100644 index 00000000000..cc2e1594a45 --- /dev/null +++ b/pkg/registry/resource/resourceclaim/storage/storage_test.go @@ -0,0 +1,182 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package storage + +import ( + "testing" + + apiequality "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/diff" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/apiserver/pkg/registry/generic" + genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing" + "k8s.io/apiserver/pkg/registry/rest" + etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing" + "k8s.io/kubernetes/pkg/apis/resource" + _ "k8s.io/kubernetes/pkg/apis/resource/install" + "k8s.io/kubernetes/pkg/registry/registrytest" +) + +func newStorage(t *testing.T) (*REST, *StatusREST, *etcd3testing.EtcdTestServer) { + etcdStorage, server := registrytest.NewEtcdStorage(t, resource.GroupName) + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "resourceclaims", + } + resourceClaimStorage, statusStorage, err := NewREST(restOptions) + if err != nil { + t.Fatalf("unexpected error from REST storage: %v", err) + } + return resourceClaimStorage, statusStorage, server +} + +func validNewClaim(name, ns string) *resource.ResourceClaim { + claim := &resource.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: ns, + }, + Spec: resource.ResourceClaimSpec{ + ResourceClassName: "example", + AllocationMode: resource.AllocationModeImmediate, + }, + Status: resource.ResourceClaimStatus{}, + } + return claim +} + +func TestCreate(t *testing.T) { + storage, _, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + claim := validNewClaim("foo", metav1.NamespaceDefault) + claim.ObjectMeta = metav1.ObjectMeta{} + test.TestCreate( + // valid + claim, + // invalid + &resource.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{Name: "*BadName!"}, + }, + ) +} + +func TestUpdate(t *testing.T) { + storage, _, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + test.TestUpdate( + // valid + validNewClaim("foo", metav1.NamespaceDefault), + // updateFunc + func(obj runtime.Object) runtime.Object { + object := obj.(*resource.ResourceClaim) + if object.Labels == nil { + object.Labels = map[string]string{} + } + object.Labels["foo"] = "bar" + return object + }, + ) +} + +func TestDelete(t *testing.T) { + storage, _, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store).ReturnDeletedObject() + test.TestDelete(validNewClaim("foo", metav1.NamespaceDefault)) +} + +func TestGet(t *testing.T) { + storage, _, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + test.TestGet(validNewClaim("foo", metav1.NamespaceDefault)) +} + +func TestList(t *testing.T) { + storage, _, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + test.TestList(validNewClaim("foo", metav1.NamespaceDefault)) +} + +func TestWatch(t *testing.T) { + storage, _, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + test.TestWatch( + validNewClaim("foo", metav1.NamespaceDefault), + // matching labels + []labels.Set{}, + // not matching labels + []labels.Set{ + {"foo": "bar"}, + }, + // matching fields + []fields.Set{ + {"metadata.name": "foo"}, + }, + // not matching fields + []fields.Set{ + {"metadata.name": "bar"}, + }, + ) +} + +func TestUpdateStatus(t *testing.T) { + storage, statusStorage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + ctx := genericapirequest.NewDefaultContext() + + key, _ := storage.KeyFunc(ctx, "foo") + claimStart := validNewClaim("foo", metav1.NamespaceDefault) + err := storage.Storage.Create(ctx, key, claimStart, nil, 0, false) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + claim := claimStart.DeepCopy() + claim.Status.DriverName = "some-driver.example.com" + claim.Status.Allocation = &resource.AllocationResult{} + _, _, err = statusStorage.Update(ctx, claim.Name, rest.DefaultUpdatedObjectInfo(claim), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + obj, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + claimOut := obj.(*resource.ResourceClaim) + // only compare relevant changes b/c of difference in metadata + if !apiequality.Semantic.DeepEqual(claim.Status, claimOut.Status) { + t.Errorf("unexpected object: %s", diff.ObjectDiff(claim.Status, claimOut.Status)) + } +} diff --git a/pkg/registry/resource/resourceclaim/strategy.go b/pkg/registry/resource/resourceclaim/strategy.go new file mode 100644 index 00000000000..8b71300de85 --- /dev/null +++ b/pkg/registry/resource/resourceclaim/strategy.go @@ -0,0 +1,163 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourceclaim + +import ( + "context" + "errors" + + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/apiserver/pkg/registry/generic" + "k8s.io/apiserver/pkg/storage" + "k8s.io/apiserver/pkg/storage/names" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/kubernetes/pkg/apis/resource/validation" + "sigs.k8s.io/structured-merge-diff/v4/fieldpath" +) + +// resourceclaimStrategy implements behavior for ResourceClaim objects +type resourceclaimStrategy struct { + runtime.ObjectTyper + names.NameGenerator +} + +// Strategy is the default logic that applies when creating and updating +// ResourceClaim objects via the REST API. +var Strategy = resourceclaimStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} + +func (resourceclaimStrategy) NamespaceScoped() bool { + return true +} + +// GetResetFields returns the set of fields that get reset by the strategy and +// should not be modified by the user. For a new ResourceClaim that is the +// status. +func (resourceclaimStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { + fields := map[fieldpath.APIVersion]*fieldpath.Set{ + "resource.k8s.io/v1alpha1": fieldpath.NewSet( + fieldpath.MakePathOrDie("status"), + ), + } + + return fields +} + +func (resourceclaimStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { + claim := obj.(*resource.ResourceClaim) + // Status must not be set by user on create. + claim.Status = resource.ResourceClaimStatus{} +} + +func (resourceclaimStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { + claim := obj.(*resource.ResourceClaim) + return validation.ValidateClaim(claim) +} + +func (resourceclaimStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string { + return nil +} + +func (resourceclaimStrategy) Canonicalize(obj runtime.Object) { +} + +func (resourceclaimStrategy) AllowCreateOnUpdate() bool { + return false +} + +func (resourceclaimStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { + newClaim := obj.(*resource.ResourceClaim) + oldClaim := old.(*resource.ResourceClaim) + newClaim.Status = oldClaim.Status +} + +func (resourceclaimStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { + newClaim := obj.(*resource.ResourceClaim) + oldClaim := old.(*resource.ResourceClaim) + errorList := validation.ValidateClaim(newClaim) + return append(errorList, validation.ValidateClaimUpdate(newClaim, oldClaim)...) +} + +func (resourceclaimStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { + return nil +} + +func (resourceclaimStrategy) AllowUnconditionalUpdate() bool { + return true +} + +type resourceclaimStatusStrategy struct { + resourceclaimStrategy +} + +var StatusStrategy = resourceclaimStatusStrategy{Strategy} + +// GetResetFields returns the set of fields that get reset by the strategy and +// should not be modified by the user. For a status update that is the spec. +func (resourceclaimStatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set { + fields := map[fieldpath.APIVersion]*fieldpath.Set{ + "resource.k8s.io/v1alpha1": fieldpath.NewSet( + fieldpath.MakePathOrDie("spec"), + ), + } + + return fields +} + +func (resourceclaimStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { + newClaim := obj.(*resource.ResourceClaim) + oldClaim := old.(*resource.ResourceClaim) + newClaim.Spec = oldClaim.Spec +} + +func (resourceclaimStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { + newClaim := obj.(*resource.ResourceClaim) + oldClaim := old.(*resource.ResourceClaim) + return validation.ValidateClaimStatusUpdate(newClaim, oldClaim) +} + +// WarningsOnUpdate returns warnings for the given update. +func (resourceclaimStatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { + return nil +} + +// Match returns a generic matcher for a given label and field selector. +func Match(label labels.Selector, field fields.Selector) storage.SelectionPredicate { + return storage.SelectionPredicate{ + Label: label, + Field: field, + GetAttrs: GetAttrs, + } +} + +// GetAttrs returns labels and fields of a given object for filtering purposes. +func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { + claim, ok := obj.(*resource.ResourceClaim) + if !ok { + return nil, nil, errors.New("not a resourceclaim") + } + return labels.Set(claim.Labels), toSelectableFields(claim), nil +} + +// toSelectableFields returns a field set that represents the object +func toSelectableFields(claim *resource.ResourceClaim) fields.Set { + fields := generic.ObjectMetaFieldsSet(&claim.ObjectMeta, true) + return fields +} diff --git a/pkg/registry/resource/resourceclaim/strategy_test.go b/pkg/registry/resource/resourceclaim/strategy_test.go new file mode 100644 index 00000000000..d4091893b5b --- /dev/null +++ b/pkg/registry/resource/resourceclaim/strategy_test.go @@ -0,0 +1,85 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourceclaim + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/kubernetes/pkg/apis/resource" +) + +var resourceClaim = &resource.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "valid-claim", + Namespace: "default", + }, + Spec: resource.ResourceClaimSpec{ + ResourceClassName: "valid-class", + AllocationMode: resource.AllocationModeImmediate, + }, +} + +func TestClaimStrategy(t *testing.T) { + if !Strategy.NamespaceScoped() { + t.Errorf("ResourceClaim must be namespace scoped") + } + if Strategy.AllowCreateOnUpdate() { + t.Errorf("ResourceClaim should not allow create on update") + } +} + +func TestClaimStrategyCreate(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() + resourceClaim := resourceClaim.DeepCopy() + + Strategy.PrepareForCreate(ctx, resourceClaim) + errs := Strategy.Validate(ctx, resourceClaim) + if len(errs) != 0 { + t.Errorf("unexpected error validating for create %v", errs) + } +} + +func TestClaimStrategyUpdate(t *testing.T) { + t.Run("no-changes-okay", func(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() + resourceClaim := resourceClaim.DeepCopy() + newClaim := resourceClaim.DeepCopy() + newClaim.ResourceVersion = "4" + + Strategy.PrepareForUpdate(ctx, newClaim, resourceClaim) + errs := Strategy.ValidateUpdate(ctx, newClaim, resourceClaim) + if len(errs) != 0 { + t.Errorf("unexpected validation errors: %v", errs) + } + }) + + t.Run("name-change-not-allowed", func(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() + resourceClaim := resourceClaim.DeepCopy() + newClaim := resourceClaim.DeepCopy() + newClaim.Name = "valid-claim-2" + newClaim.ResourceVersion = "4" + + Strategy.PrepareForUpdate(ctx, newClaim, resourceClaim) + errs := Strategy.ValidateUpdate(ctx, newClaim, resourceClaim) + if len(errs) == 0 { + t.Errorf("expected a validation error") + } + }) +} diff --git a/pkg/registry/resource/resourceclaimtemplate/storage/storage.go b/pkg/registry/resource/resourceclaimtemplate/storage/storage.go new file mode 100644 index 00000000000..282db91006d --- /dev/null +++ b/pkg/registry/resource/resourceclaimtemplate/storage/storage.go @@ -0,0 +1,55 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package storage + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/registry/generic" + genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/kubernetes/pkg/printers" + printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" + printerstorage "k8s.io/kubernetes/pkg/printers/storage" + "k8s.io/kubernetes/pkg/registry/resource/resourceclaimtemplate" +) + +// REST implements a RESTStorage for ResourceClaimTemplate. +type REST struct { + *genericregistry.Store +} + +// NewREST returns a RESTStorage object that will work against ResourceClass. +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { + store := &genericregistry.Store{ + NewFunc: func() runtime.Object { return &resource.ResourceClaimTemplate{} }, + NewListFunc: func() runtime.Object { return &resource.ResourceClaimTemplateList{} }, + DefaultQualifiedResource: resource.Resource("resourceclaimtemplates"), + + CreateStrategy: resourceclaimtemplate.Strategy, + UpdateStrategy: resourceclaimtemplate.Strategy, + DeleteStrategy: resourceclaimtemplate.Strategy, + ReturnDeletedObject: true, + + TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)}, + } + options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: resourceclaimtemplate.GetAttrs} + if err := store.CompleteWithOptions(options); err != nil { + return nil, err + } + + return &REST{store}, nil +} diff --git a/pkg/registry/resource/resourceclaimtemplate/storage/storage_test.go b/pkg/registry/resource/resourceclaimtemplate/storage/storage_test.go new file mode 100644 index 00000000000..642938b3bc2 --- /dev/null +++ b/pkg/registry/resource/resourceclaimtemplate/storage/storage_test.go @@ -0,0 +1,151 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package storage + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/registry/generic" + genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing" + etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing" + "k8s.io/kubernetes/pkg/apis/resource" + _ "k8s.io/kubernetes/pkg/apis/resource/install" + "k8s.io/kubernetes/pkg/registry/registrytest" +) + +func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) { + etcdStorage, server := registrytest.NewEtcdStorage(t, resource.GroupName) + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "resourceclaimtemplates", + } + resourceClaimTemplateStorage, err := NewREST(restOptions) + if err != nil { + t.Fatalf("unexpected error from REST storage: %v", err) + } + return resourceClaimTemplateStorage, server +} + +func validNewClaimTemplate(name string) *resource.ResourceClaimTemplate { + return &resource.ResourceClaimTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: metav1.NamespaceDefault, + }, + Spec: resource.ResourceClaimTemplateSpec{ + Spec: resource.ResourceClaimSpec{ + ResourceClassName: "valid-class", + AllocationMode: resource.AllocationModeImmediate, + }, + }, + } +} + +func TestCreate(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + resourceClaimTemplate := validNewClaimTemplate("foo") + resourceClaimTemplate.ObjectMeta = metav1.ObjectMeta{GenerateName: "foo"} + test.TestCreate( + // valid + resourceClaimTemplate, + // invalid + &resource.ResourceClaimTemplate{ + ObjectMeta: metav1.ObjectMeta{Name: "*BadName!"}, + }, + ) +} + +func TestUpdate(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + test.TestUpdate( + // valid + validNewClaimTemplate("foo"), + // updateFunc + func(obj runtime.Object) runtime.Object { + object := obj.(*resource.ResourceClaimTemplate) + object.Labels = map[string]string{"a": "b"} + return object + }, + //invalid update + func(obj runtime.Object) runtime.Object { + object := obj.(*resource.ResourceClaimTemplate) + object.Spec.Spec.ResourceClassName = "" + return object + }, + ) + +} + +func TestDelete(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store).ReturnDeletedObject() + test.TestDelete(validNewClaimTemplate("foo")) +} + +func TestGet(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + test.TestGet(validNewClaimTemplate("foo")) +} + +func TestList(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + test.TestList(validNewClaimTemplate("foo")) +} + +func TestWatch(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store) + test.TestWatch( + validNewClaimTemplate("foo"), + // matching labels + []labels.Set{}, + // not matching labels + []labels.Set{ + {"foo": "bar"}, + }, + // matching fields + []fields.Set{ + {"metadata.name": "foo"}, + }, + // not matching fields + []fields.Set{ + {"metadata.name": "bar"}, + }, + ) +} diff --git a/pkg/registry/resource/resourceclaimtemplate/strategy.go b/pkg/registry/resource/resourceclaimtemplate/strategy.go new file mode 100644 index 00000000000..8c625c94d4b --- /dev/null +++ b/pkg/registry/resource/resourceclaimtemplate/strategy.go @@ -0,0 +1,94 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourceclaimtemplate + +import ( + "context" + "errors" + + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/apiserver/pkg/registry/generic" + "k8s.io/apiserver/pkg/storage/names" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/kubernetes/pkg/apis/resource/validation" +) + +// resourceClaimTemplateStrategy implements behavior for ResourceClaimTemplate objects +type resourceClaimTemplateStrategy struct { + runtime.ObjectTyper + names.NameGenerator +} + +var Strategy = resourceClaimTemplateStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} + +func (resourceClaimTemplateStrategy) NamespaceScoped() bool { + return true +} + +func (resourceClaimTemplateStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { +} + +func (resourceClaimTemplateStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { + resourceClaimTemplate := obj.(*resource.ResourceClaimTemplate) + return validation.ValidateClaimTemplate(resourceClaimTemplate) +} + +func (resourceClaimTemplateStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string { + return nil +} + +func (resourceClaimTemplateStrategy) Canonicalize(obj runtime.Object) { +} + +func (resourceClaimTemplateStrategy) AllowCreateOnUpdate() bool { + return false +} + +func (resourceClaimTemplateStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { +} + +func (resourceClaimTemplateStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { + errorList := validation.ValidateClaimTemplate(obj.(*resource.ResourceClaimTemplate)) + return append(errorList, validation.ValidateClaimTemplateUpdate(obj.(*resource.ResourceClaimTemplate), old.(*resource.ResourceClaimTemplate))...) +} + +func (resourceClaimTemplateStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { + return nil +} + +func (resourceClaimTemplateStrategy) AllowUnconditionalUpdate() bool { + return true +} + +// GetAttrs returns labels and fields of a given object for filtering purposes. +func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { + template, ok := obj.(*resource.ResourceClaimTemplate) + if !ok { + return nil, nil, errors.New("not a resourceclaimtemplate") + } + return labels.Set(template.Labels), toSelectableFields(template), nil +} + +// toSelectableFields returns a field set that represents the object +func toSelectableFields(template *resource.ResourceClaimTemplate) fields.Set { + fields := generic.ObjectMetaFieldsSet(&template.ObjectMeta, true) + return fields +} diff --git a/pkg/registry/resource/resourceclaimtemplate/strategy_test.go b/pkg/registry/resource/resourceclaimtemplate/strategy_test.go new file mode 100644 index 00000000000..47e25375321 --- /dev/null +++ b/pkg/registry/resource/resourceclaimtemplate/strategy_test.go @@ -0,0 +1,87 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourceclaimtemplate + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/kubernetes/pkg/apis/resource" +) + +var resourceClaimTemplate = &resource.ResourceClaimTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Name: "valid-claim-template", + Namespace: "default", + }, + Spec: resource.ResourceClaimTemplateSpec{ + Spec: resource.ResourceClaimSpec{ + ResourceClassName: "valid-class", + AllocationMode: resource.AllocationModeImmediate, + }, + }, +} + +func TestClaimTemplateStrategy(t *testing.T) { + if !Strategy.NamespaceScoped() { + t.Errorf("ResourceClaimTemplate must be namespace scoped") + } + if Strategy.AllowCreateOnUpdate() { + t.Errorf("ResourceClaimTemplate should not allow create on update") + } +} + +func TestClaimTemplateStrategyCreate(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() + resourceClaimTemplate := resourceClaimTemplate.DeepCopy() + + Strategy.PrepareForCreate(ctx, resourceClaimTemplate) + errs := Strategy.Validate(ctx, resourceClaimTemplate) + if len(errs) != 0 { + t.Errorf("unexpected error validating for create %v", errs) + } +} + +func TestClaimTemplateStrategyUpdate(t *testing.T) { + t.Run("no-changes-okay", func(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() + resourceClaimTemplate := resourceClaimTemplate.DeepCopy() + newClaimTemplate := resourceClaimTemplate.DeepCopy() + newClaimTemplate.ResourceVersion = "4" + + Strategy.PrepareForUpdate(ctx, newClaimTemplate, resourceClaimTemplate) + errs := Strategy.ValidateUpdate(ctx, newClaimTemplate, resourceClaimTemplate) + if len(errs) != 0 { + t.Errorf("unexpected validation errors: %v", errs) + } + }) + + t.Run("name-change-not-allowed", func(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() + resourceClaimTemplate := resourceClaimTemplate.DeepCopy() + newClaimTemplate := resourceClaimTemplate.DeepCopy() + newClaimTemplate.Name = "valid-class-2" + newClaimTemplate.ResourceVersion = "4" + + Strategy.PrepareForUpdate(ctx, newClaimTemplate, resourceClaimTemplate) + errs := Strategy.ValidateUpdate(ctx, newClaimTemplate, resourceClaimTemplate) + if len(errs) == 0 { + t.Errorf("expected a validation error") + } + }) +} diff --git a/pkg/registry/resource/resourceclass/storage/storage.go b/pkg/registry/resource/resourceclass/storage/storage.go new file mode 100644 index 00000000000..310488ab04e --- /dev/null +++ b/pkg/registry/resource/resourceclass/storage/storage.go @@ -0,0 +1,55 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package storage + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/registry/generic" + genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/kubernetes/pkg/printers" + printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" + printerstorage "k8s.io/kubernetes/pkg/printers/storage" + "k8s.io/kubernetes/pkg/registry/resource/resourceclass" +) + +// REST implements a RESTStorage for ResourceClass. +type REST struct { + *genericregistry.Store +} + +// NewREST returns a RESTStorage object that will work against ResourceClass. +func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, error) { + store := &genericregistry.Store{ + NewFunc: func() runtime.Object { return &resource.ResourceClass{} }, + NewListFunc: func() runtime.Object { return &resource.ResourceClassList{} }, + DefaultQualifiedResource: resource.Resource("resourceclasses"), + + CreateStrategy: resourceclass.Strategy, + UpdateStrategy: resourceclass.Strategy, + DeleteStrategy: resourceclass.Strategy, + ReturnDeletedObject: true, + + TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)}, + } + options := &generic.StoreOptions{RESTOptions: optsGetter} + if err := store.CompleteWithOptions(options); err != nil { + return nil, err + } + + return &REST{store}, nil +} diff --git a/pkg/registry/resource/resourceclass/storage/storage_test.go b/pkg/registry/resource/resourceclass/storage/storage_test.go new file mode 100644 index 00000000000..817623e7acc --- /dev/null +++ b/pkg/registry/resource/resourceclass/storage/storage_test.go @@ -0,0 +1,145 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package storage + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/registry/generic" + genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing" + etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing" + "k8s.io/kubernetes/pkg/apis/resource" + _ "k8s.io/kubernetes/pkg/apis/resource/install" + "k8s.io/kubernetes/pkg/registry/registrytest" +) + +func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) { + etcdStorage, server := registrytest.NewEtcdStorage(t, resource.GroupName) + restOptions := generic.RESTOptions{ + StorageConfig: etcdStorage, + Decorator: generic.UndecoratedStorage, + DeleteCollectionWorkers: 1, + ResourcePrefix: "resourceclasses", + } + resourceClassStorage, err := NewREST(restOptions) + if err != nil { + t.Fatalf("unexpected error from REST storage: %v", err) + } + return resourceClassStorage, server +} + +func validNewClass(name string) *resource.ResourceClass { + return &resource.ResourceClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + DriverName: "cdi.example.com", + } +} + +func TestCreate(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store).ClusterScope() + resourceClass := validNewClass("foo") + resourceClass.ObjectMeta = metav1.ObjectMeta{GenerateName: "foo"} + test.TestCreate( + // valid + resourceClass, + // invalid + &resource.ResourceClass{ + ObjectMeta: metav1.ObjectMeta{Name: "*BadName!"}, + }, + ) +} + +func TestUpdate(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store).ClusterScope() + test.TestUpdate( + // valid + validNewClass("foo"), + // updateFunc + func(obj runtime.Object) runtime.Object { + object := obj.(*resource.ResourceClass) + object.ParametersRef = &resource.ResourceClassParametersReference{Kind: "cdiexample", Name: "some-name"} + return object + }, + //invalid update + func(obj runtime.Object) runtime.Object { + object := obj.(*resource.ResourceClass) + object.DriverName = "" + return object + }, + ) + +} + +func TestDelete(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store).ClusterScope().ReturnDeletedObject() + test.TestDelete(validNewClass("foo")) +} + +func TestGet(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store).ClusterScope() + test.TestGet(validNewClass("foo")) +} + +func TestList(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store).ClusterScope() + test.TestList(validNewClass("foo")) +} + +func TestWatch(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() + test := genericregistrytest.New(t, storage.Store).ClusterScope() + test.TestWatch( + validNewClass("foo"), + // matching labels + []labels.Set{}, + // not matching labels + []labels.Set{ + {"foo": "bar"}, + }, + // matching fields + []fields.Set{ + {"metadata.name": "foo"}, + }, + // not matching fields + []fields.Set{ + {"metadata.name": "bar"}, + }, + ) +} diff --git a/pkg/registry/resource/resourceclass/strategy.go b/pkg/registry/resource/resourceclass/strategy.go new file mode 100644 index 00000000000..55f98fe4065 --- /dev/null +++ b/pkg/registry/resource/resourceclass/strategy.go @@ -0,0 +1,75 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourceclass + +import ( + "context" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/apiserver/pkg/storage/names" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/apis/resource" + "k8s.io/kubernetes/pkg/apis/resource/validation" +) + +// resourceClassStrategy implements behavior for ResourceClass objects +type resourceClassStrategy struct { + runtime.ObjectTyper + names.NameGenerator +} + +var Strategy = resourceClassStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} + +func (resourceClassStrategy) NamespaceScoped() bool { + return false +} + +func (resourceClassStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { +} + +func (resourceClassStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { + resourceClass := obj.(*resource.ResourceClass) + return validation.ValidateClass(resourceClass) +} + +func (resourceClassStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string { + return nil +} + +func (resourceClassStrategy) Canonicalize(obj runtime.Object) { +} + +func (resourceClassStrategy) AllowCreateOnUpdate() bool { + return false +} + +func (resourceClassStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { +} + +func (resourceClassStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { + errorList := validation.ValidateClass(obj.(*resource.ResourceClass)) + return append(errorList, validation.ValidateClassUpdate(obj.(*resource.ResourceClass), old.(*resource.ResourceClass))...) +} + +func (resourceClassStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { + return nil +} + +func (resourceClassStrategy) AllowUnconditionalUpdate() bool { + return true +} diff --git a/pkg/registry/resource/resourceclass/strategy_test.go b/pkg/registry/resource/resourceclass/strategy_test.go new file mode 100644 index 00000000000..d55f8066769 --- /dev/null +++ b/pkg/registry/resource/resourceclass/strategy_test.go @@ -0,0 +1,81 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourceclass + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/kubernetes/pkg/apis/resource" +) + +var resourceClass = &resource.ResourceClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: "valid-class", + }, + DriverName: "resource-driver.example.com", +} + +func TestClassStrategy(t *testing.T) { + if Strategy.NamespaceScoped() { + t.Errorf("ResourceClass must not be namespace scoped") + } + if Strategy.AllowCreateOnUpdate() { + t.Errorf("ResourceClass should not allow create on update") + } +} + +func TestClassStrategyCreate(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() + resourceClass := resourceClass.DeepCopy() + + Strategy.PrepareForCreate(ctx, resourceClass) + errs := Strategy.Validate(ctx, resourceClass) + if len(errs) != 0 { + t.Errorf("unexpected error validating for create %v", errs) + } +} + +func TestClassStrategyUpdate(t *testing.T) { + t.Run("no-changes-okay", func(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() + resourceClass := resourceClass.DeepCopy() + newClass := resourceClass.DeepCopy() + newClass.ResourceVersion = "4" + + Strategy.PrepareForUpdate(ctx, newClass, resourceClass) + errs := Strategy.ValidateUpdate(ctx, newClass, resourceClass) + if len(errs) != 0 { + t.Errorf("unexpected validation errors: %v", errs) + } + }) + + t.Run("name-change-not-allowed", func(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() + resourceClass := resourceClass.DeepCopy() + newClass := resourceClass.DeepCopy() + newClass.Name = "valid-class-2" + newClass.ResourceVersion = "4" + + Strategy.PrepareForUpdate(ctx, newClass, resourceClass) + errs := Strategy.ValidateUpdate(ctx, newClass, resourceClass) + if len(errs) == 0 { + t.Errorf("expected a validation error") + } + }) +} diff --git a/pkg/registry/resource/rest/storage_resource.go b/pkg/registry/resource/rest/storage_resource.go new file mode 100644 index 00000000000..93d793e466a --- /dev/null +++ b/pkg/registry/resource/rest/storage_resource.go @@ -0,0 +1,91 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rest + +import ( + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + "k8s.io/apiserver/pkg/registry/generic" + "k8s.io/apiserver/pkg/registry/rest" + genericapiserver "k8s.io/apiserver/pkg/server" + serverstorage "k8s.io/apiserver/pkg/server/storage" + "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/kubernetes/pkg/apis/resource" + podschedulingstore "k8s.io/kubernetes/pkg/registry/resource/podscheduling/storage" + resourceclaimstore "k8s.io/kubernetes/pkg/registry/resource/resourceclaim/storage" + resourceclaimtemplatestore "k8s.io/kubernetes/pkg/registry/resource/resourceclaimtemplate/storage" + resourceclassstore "k8s.io/kubernetes/pkg/registry/resource/resourceclass/storage" +) + +type RESTStorageProvider struct{} + +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(resource.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) + // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. + // TODO refactor the plumbing to provide the information in the APIGroupInfo + + if storageMap, err := p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { + return genericapiserver.APIGroupInfo{}, err + } else if len(storageMap) > 0 { + apiGroupInfo.VersionedResourcesStorageMap[resourcev1alpha1.SchemeGroupVersion.Version] = storageMap + } + + return apiGroupInfo, nil +} + +func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { + storage := map[string]rest.Storage{} + + if resource := "resourceclasses"; apiResourceConfigSource.ResourceEnabled(resourcev1alpha1.SchemeGroupVersion.WithResource(resource)) { + resourceClassStorage, err := resourceclassstore.NewREST(restOptionsGetter) + if err != nil { + return nil, err + } + storage[resource] = resourceClassStorage + } + + if resource := "resourceclaims"; apiResourceConfigSource.ResourceEnabled(resourcev1alpha1.SchemeGroupVersion.WithResource(resource)) { + resourceClaimStorage, resourceClaimStatusStorage, err := resourceclaimstore.NewREST(restOptionsGetter) + if err != nil { + return nil, err + } + storage[resource] = resourceClaimStorage + storage[resource+"/status"] = resourceClaimStatusStorage + } + + if resource := "resourceclaimtemplates"; apiResourceConfigSource.ResourceEnabled(resourcev1alpha1.SchemeGroupVersion.WithResource(resource)) { + resourceClaimTemplateStorage, err := resourceclaimtemplatestore.NewREST(restOptionsGetter) + if err != nil { + return nil, err + } + storage[resource] = resourceClaimTemplateStorage + } + + if resource := "podschedulings"; apiResourceConfigSource.ResourceEnabled(resourcev1alpha1.SchemeGroupVersion.WithResource(resource)) { + podSchedulingStorage, podSchedulingStatusStorage, err := podschedulingstore.NewREST(restOptionsGetter) + if err != nil { + return nil, err + } + storage[resource] = podSchedulingStorage + storage[resource+"/status"] = podSchedulingStatusStorage + } + + return storage, nil +} + +func (p RESTStorageProvider) GroupName() string { + return resource.GroupName +} diff --git a/pkg/scheduler/apis/config/v1/default_plugins.go b/pkg/scheduler/apis/config/v1/default_plugins.go index daeb3370ed0..3fc8c1bdf86 100644 --- a/pkg/scheduler/apis/config/v1/default_plugins.go +++ b/pkg/scheduler/apis/config/v1/default_plugins.go @@ -63,6 +63,23 @@ func applyFeatureGates(config *v1.Plugins) { if utilfeature.DefaultFeatureGate.Enabled(features.PodSchedulingReadiness) { config.MultiPoint.Enabled = append(config.MultiPoint.Enabled, v1.Plugin{Name: names.SchedulingGates}) } + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) { + // This plugin should come before DefaultPreemption because if + // there is a problem with a Pod and PostFilter gets called to + // resolve the problem, it is better to first deallocate an + // idle ResourceClaim than it is to evict some Pod that might + // be doing useful work. + for i := range config.MultiPoint.Enabled { + if config.MultiPoint.Enabled[i].Name == names.DefaultPreemption { + extended := make([]v1.Plugin, 0, len(config.MultiPoint.Enabled)+1) + extended = append(extended, config.MultiPoint.Enabled[:i]...) + extended = append(extended, v1.Plugin{Name: names.DynamicResources}) + extended = append(extended, config.MultiPoint.Enabled[i:]...) + config.MultiPoint.Enabled = extended + break + } + } + } } // mergePlugins merges the custom set into the given default one, handling disabled sets. diff --git a/pkg/scheduler/apis/config/v1/default_plugins_test.go b/pkg/scheduler/apis/config/v1/default_plugins_test.go index d9ceb2ae527..56008a8254b 100644 --- a/pkg/scheduler/apis/config/v1/default_plugins_test.go +++ b/pkg/scheduler/apis/config/v1/default_plugins_test.go @@ -97,6 +97,39 @@ func TestApplyFeatureGates(t *testing.T) { }, }, }, + { + name: "Feature gate DynamicResourceAllocation enabled", + features: map[featuregate.Feature]bool{ + features.DynamicResourceAllocation: true, + }, + wantConfig: &v1.Plugins{ + MultiPoint: v1.PluginSet{ + Enabled: []v1.Plugin{ + {Name: names.PrioritySort}, + {Name: names.NodeUnschedulable}, + {Name: names.NodeName}, + {Name: names.TaintToleration, Weight: pointer.Int32(3)}, + {Name: names.NodeAffinity, Weight: pointer.Int32(2)}, + {Name: names.NodePorts}, + {Name: names.NodeResourcesFit, Weight: pointer.Int32(1)}, + {Name: names.VolumeRestrictions}, + {Name: names.EBSLimits}, + {Name: names.GCEPDLimits}, + {Name: names.NodeVolumeLimits}, + {Name: names.AzureDiskLimits}, + {Name: names.VolumeBinding}, + {Name: names.VolumeZone}, + {Name: names.PodTopologySpread, Weight: pointer.Int32(2)}, + {Name: names.InterPodAffinity, Weight: pointer.Int32(2)}, + {Name: names.DynamicResources}, + {Name: names.DefaultPreemption}, + {Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32(1)}, + {Name: names.ImageLocality, Weight: pointer.Int32(1)}, + {Name: names.DefaultBinder}, + }, + }, + }, + }, } for _, test := range tests { diff --git a/pkg/scheduler/eventhandlers.go b/pkg/scheduler/eventhandlers.go index 0c39dcde277..9f7b2b53d7d 100644 --- a/pkg/scheduler/eventhandlers.go +++ b/pkg/scheduler/eventhandlers.go @@ -25,12 +25,14 @@ import ( storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/runtime/schema" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/dynamic/dynamicinformer" "k8s.io/client-go/informers" "k8s.io/client-go/tools/cache" corev1helpers "k8s.io/component-helpers/scheduling/corev1" corev1nodeaffinity "k8s.io/component-helpers/scheduling/corev1/nodeaffinity" "k8s.io/klog/v2" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeaffinity" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodename" @@ -376,6 +378,18 @@ func addAllEventHandlers( informerFactory.Core().V1().PersistentVolumeClaims().Informer().AddEventHandler( buildEvtResHandler(at, framework.PersistentVolumeClaim, "Pvc"), ) + case framework.PodScheduling: + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) { + _, _ = informerFactory.Resource().V1alpha1().PodSchedulings().Informer().AddEventHandler( + buildEvtResHandler(at, framework.PodScheduling, "PodScheduling"), + ) + } + case framework.ResourceClaim: + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) { + _, _ = informerFactory.Resource().V1alpha1().ResourceClaims().Informer().AddEventHandler( + buildEvtResHandler(at, framework.ResourceClaim, "ResourceClaim"), + ) + } case framework.StorageClass: if at&framework.Add != 0 { informerFactory.Storage().V1().StorageClasses().Informer().AddEventHandler( diff --git a/pkg/scheduler/framework/plugins/dynamicresources/OWNERS b/pkg/scheduler/framework/plugins/dynamicresources/OWNERS new file mode 100644 index 00000000000..98ccc3b8054 --- /dev/null +++ b/pkg/scheduler/framework/plugins/dynamicresources/OWNERS @@ -0,0 +1,8 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +reviewers: + - klueska + - pohly + - bart0sh +labels: + - sig/node diff --git a/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources.go b/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources.go new file mode 100644 index 00000000000..7d3c9f9f97a --- /dev/null +++ b/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources.go @@ -0,0 +1,804 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dynamicresources + +import ( + "context" + "errors" + "fmt" + "sort" + "sync" + + v1 "k8s.io/api/core/v1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/client-go/kubernetes" + resourcev1alpha1listers "k8s.io/client-go/listers/resource/v1alpha1" + corev1helpers "k8s.io/component-helpers/scheduling/corev1" + "k8s.io/component-helpers/scheduling/corev1/nodeaffinity" + "k8s.io/dynamic-resource-allocation/resourceclaim" + "k8s.io/klog/v2" + "k8s.io/kubernetes/pkg/scheduler/framework" + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature" + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/names" +) + +const ( + // Name is the name of the plugin used in Registry and configurations. + Name = names.DynamicResources + + stateKey framework.StateKey = Name +) + +// The state is initialized in PreFilter phase. Because we save the pointer in +// framework.CycleState, in the later phases we don't need to call Write method +// to update the value +type stateData struct { + // A copy of all claims for the Pod (i.e. 1:1 match with + // pod.Spec.ResourceClaims), initially with the status from the start + // of the scheduling cycle. Each claim instance is read-only because it + // might come from the informer cache. The instances get replaced when + // the plugin itself successfully does an Update. + // + // Empty if the Pod has no claims. + claims []*resourcev1alpha1.ResourceClaim + + // The AvailableOnNodes node filters of the claims converted from the + // v1 API to nodeaffinity.NodeSelector by PreFilter for repeated + // evaluation in Filter. Nil for claims which don't have it. + availableOnNodes []*nodeaffinity.NodeSelector + + // The indices of all claims that: + // - are allocated + // - use delayed allocation + // - were not available on at least one node + // + // Set in parallel during Filter, so write access there must be + // protected by the mutex. Used by PostFilter. + unavailableClaims sets.Int + + // A pointer to the PodScheduling object for the pod, if one exists. + // Gets set on demand. + // + // Conceptually, this object belongs into the scheduler framework + // where it might get shared by different plugins. But in practice, + // it is currently only used by dynamic provisioning and thus + // managed entirely here. + podScheduling *resourcev1alpha1.PodScheduling + + // podSchedulingDirty is true if the current copy was locally modified. + podSchedulingDirty bool + + mutex sync.Mutex +} + +func (d *stateData) Clone() framework.StateData { + return d +} + +func (d *stateData) updateClaimStatus(ctx context.Context, clientset kubernetes.Interface, index int, claim *resourcev1alpha1.ResourceClaim) error { + // TODO (#113700): replace with patch operation. Beware that patching must only succeed if the + // object has not been modified in parallel by someone else. + claim, err := clientset.ResourceV1alpha1().ResourceClaims(claim.Namespace).UpdateStatus(ctx, claim, metav1.UpdateOptions{}) + // TODO: metric for update results, with the operation ("set selected + // node", "set PotentialNodes", etc.) as one dimension. + if err != nil { + return fmt.Errorf("update resource claim: %w", err) + } + + // Remember the new instance. This is relevant when the plugin must + // update the same claim multiple times (for example, first reserve + // the claim, then later remove the reservation), because otherwise the second + // update would fail with a "was modified" error. + d.claims[index] = claim + + return nil +} + +// initializePodScheduling can be called concurrently. It returns an existing PodScheduling +// object if there is one already, retrieves one if not, or as a last resort creates +// one from scratch. +func (d *stateData) initializePodScheduling(ctx context.Context, pod *v1.Pod, podSchedulingLister resourcev1alpha1listers.PodSchedulingLister) (*resourcev1alpha1.PodScheduling, error) { + // TODO (#113701): check if this mutex locking can be avoided by calling initializePodScheduling during PreFilter. + d.mutex.Lock() + defer d.mutex.Unlock() + + if d.podScheduling != nil { + return d.podScheduling, nil + } + + podScheduling, err := podSchedulingLister.PodSchedulings(pod.Namespace).Get(pod.Name) + switch { + case apierrors.IsNotFound(err): + controller := true + podScheduling = &resourcev1alpha1.PodScheduling{ + ObjectMeta: metav1.ObjectMeta{ + Name: pod.Name, + Namespace: pod.Namespace, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "v1", + Kind: "Pod", + Name: pod.Name, + UID: pod.UID, + Controller: &controller, + }, + }, + }, + } + err = nil + case err != nil: + return nil, err + default: + // We have an object, but it might be obsolete. + if !metav1.IsControlledBy(podScheduling, pod) { + return nil, fmt.Errorf("PodScheduling object with UID %s is not owned by Pod %s/%s", podScheduling.UID, pod.Namespace, pod.Name) + } + } + d.podScheduling = podScheduling + return podScheduling, err +} + +// publishPodScheduling creates or updates the PodScheduling object. +func (d *stateData) publishPodScheduling(ctx context.Context, clientset kubernetes.Interface, podScheduling *resourcev1alpha1.PodScheduling) error { + d.mutex.Lock() + defer d.mutex.Unlock() + + var err error + logger := klog.FromContext(ctx) + msg := "Updating PodScheduling" + if podScheduling.UID == "" { + msg = "Creating PodScheduling" + } + if loggerV := logger.V(6); loggerV.Enabled() { + // At a high enough log level, dump the entire object. + loggerV.Info(msg, "podschedulingDump", podScheduling) + } else { + logger.V(5).Info(msg, "podscheduling", klog.KObj(podScheduling)) + } + if podScheduling.UID == "" { + podScheduling, err = clientset.ResourceV1alpha1().PodSchedulings(podScheduling.Namespace).Create(ctx, podScheduling, metav1.CreateOptions{}) + } else { + // TODO (#113700): patch here to avoid racing with drivers which update the status. + podScheduling, err = clientset.ResourceV1alpha1().PodSchedulings(podScheduling.Namespace).Update(ctx, podScheduling, metav1.UpdateOptions{}) + } + if err != nil { + return err + } + d.podScheduling = podScheduling + d.podSchedulingDirty = false + return nil +} + +// storePodScheduling replaces the pod scheduling object in the state. +func (d *stateData) storePodScheduling(podScheduling *resourcev1alpha1.PodScheduling) { + d.mutex.Lock() + defer d.mutex.Unlock() + + d.podScheduling = podScheduling + d.podSchedulingDirty = true +} + +func statusForClaim(podScheduling *resourcev1alpha1.PodScheduling, podClaimName string) *resourcev1alpha1.ResourceClaimSchedulingStatus { + for _, status := range podScheduling.Status.ResourceClaims { + if status.Name == podClaimName { + return &status + } + } + return nil +} + +// dynamicResources is a plugin that ensures that ResourceClaims are allocated. +type dynamicResources struct { + enabled bool + clientset kubernetes.Interface + claimLister resourcev1alpha1listers.ResourceClaimLister + classLister resourcev1alpha1listers.ResourceClassLister + podSchedulingLister resourcev1alpha1listers.PodSchedulingLister +} + +// New initializes a new plugin and returns it. +func New(plArgs runtime.Object, fh framework.Handle, fts feature.Features) (framework.Plugin, error) { + if !fts.EnableDynamicResourceAllocation { + // Disabled, won't do anything. + return &dynamicResources{}, nil + } + + return &dynamicResources{ + enabled: true, + clientset: fh.ClientSet(), + claimLister: fh.SharedInformerFactory().Resource().V1alpha1().ResourceClaims().Lister(), + classLister: fh.SharedInformerFactory().Resource().V1alpha1().ResourceClasses().Lister(), + podSchedulingLister: fh.SharedInformerFactory().Resource().V1alpha1().PodSchedulings().Lister(), + }, nil +} + +var _ framework.PreFilterPlugin = &dynamicResources{} +var _ framework.FilterPlugin = &dynamicResources{} +var _ framework.PostFilterPlugin = &dynamicResources{} +var _ framework.PreScorePlugin = &dynamicResources{} +var _ framework.ReservePlugin = &dynamicResources{} +var _ framework.EnqueueExtensions = &dynamicResources{} +var _ framework.PostBindPlugin = &dynamicResources{} + +// Name returns name of the plugin. It is used in logs, etc. +func (pl *dynamicResources) Name() string { + return Name +} + +// EventsToRegister returns the possible events that may make a Pod +// failed by this plugin schedulable. +func (pl *dynamicResources) EventsToRegister() []framework.ClusterEvent { + if !pl.enabled { + return nil + } + + events := []framework.ClusterEvent{ + // Allocation is tracked in ResourceClaims, so any changes may make the pods schedulable. + {Resource: framework.ResourceClaim, ActionType: framework.Add | framework.Update}, + // When a driver has provided additional information, a pod waiting for that information + // may be schedulable. + // TODO (#113702): can we change this so that such an event does not trigger *all* pods? + // Yes: https://github.com/kubernetes/kubernetes/blob/abcbaed0784baf5ed2382aae9705a8918f2daa18/pkg/scheduler/eventhandlers.go#L70 + {Resource: framework.PodScheduling, ActionType: framework.Add | framework.Update}, + // A resource might depend on node labels for topology filtering. + // A new or updated node may make pods schedulable. + {Resource: framework.Node, ActionType: framework.Add | framework.UpdateNodeLabel}, + } + return events +} + +// podResourceClaims returns the ResourceClaims for all pod.Spec.PodResourceClaims. +func (pl *dynamicResources) podResourceClaims(pod *v1.Pod) ([]*resourcev1alpha1.ResourceClaim, error) { + claims := make([]*resourcev1alpha1.ResourceClaim, 0, len(pod.Spec.ResourceClaims)) + for _, resource := range pod.Spec.ResourceClaims { + claimName := resourceclaim.Name(pod, &resource) + isEphemeral := resource.Source.ResourceClaimTemplateName != nil + claim, err := pl.claimLister.ResourceClaims(pod.Namespace).Get(claimName) + if err != nil { + // The error usually has already enough context ("resourcevolumeclaim "myclaim" not found"), + // but we can do better for generic ephemeral inline volumes where that situation + // is normal directly after creating a pod. + if isEphemeral && apierrors.IsNotFound(err) { + err = fmt.Errorf("waiting for dynamic resource controller to create the resourceclaim %q", claimName) + } + return nil, err + } + + if claim.DeletionTimestamp != nil { + return nil, fmt.Errorf("resourceclaim %q is being deleted", claim.Name) + } + + if isEphemeral { + if err := resourceclaim.IsForPod(pod, claim); err != nil { + return nil, err + } + } + // We store the pointer as returned by the lister. The + // assumption is that if a claim gets modified while our code + // runs, the cache will store a new pointer, not mutate the + // existing object that we point to here. + claims = append(claims, claim) + } + return claims, nil +} + +// PreFilter invoked at the prefilter extension point to check if pod has all +// immediate claims bound. UnschedulableAndUnresolvable is returned if +// the pod cannot be scheduled at the moment on any node. +func (pl *dynamicResources) PreFilter(ctx context.Context, state *framework.CycleState, pod *v1.Pod) (*framework.PreFilterResult, *framework.Status) { + if !pl.enabled { + return nil, nil + } + logger := klog.FromContext(ctx) + + // If the pod does not reference any claim, we don't need to do + // anything for it. We just initialize an empty state to record that + // observation for the other functions. This gets updated below + // if we get that far. + s := &stateData{} + state.Write(stateKey, s) + + claims, err := pl.podResourceClaims(pod) + if err != nil { + return nil, statusUnschedulable(logger, err.Error()) + } + logger.V(5).Info("pod resource claims", "pod", klog.KObj(pod), "resourceclaims", klog.KObjs(claims)) + // If the pod does not reference any claim, we don't need to do + // anything for it. + if len(claims) == 0 { + return nil, nil + } + + s.availableOnNodes = make([]*nodeaffinity.NodeSelector, len(claims)) + for index, claim := range claims { + if claim.Spec.AllocationMode == resourcev1alpha1.AllocationModeImmediate && + claim.Status.Allocation == nil { + // This will get resolved by the resource driver. + return nil, statusUnschedulable(logger, "unallocated immediate resourceclaim", "pod", klog.KObj(pod), "resourceclaim", klog.KObj(claim)) + } + if claim.Status.DeallocationRequested { + // This will get resolved by the resource driver. + return nil, statusUnschedulable(logger, "resourceclaim must be reallocated", "pod", klog.KObj(pod), "resourceclaim", klog.KObj(claim)) + } + if claim.Status.Allocation != nil && + !resourceclaim.CanBeReserved(claim) && + !resourceclaim.IsReservedForPod(pod, claim) { + // Resource is in use. The pod has to wait. + return nil, statusUnschedulable(logger, "resourceclaim in use", "pod", klog.KObj(pod), "resourceclaim", klog.KObj(claim)) + } + if claim.Status.Allocation != nil && + claim.Status.Allocation.AvailableOnNodes != nil { + nodeSelector, err := nodeaffinity.NewNodeSelector(claim.Status.Allocation.AvailableOnNodes) + if err != nil { + return nil, statusError(logger, err) + } + s.availableOnNodes[index] = nodeSelector + } + } + + s.claims = claims + state.Write(stateKey, s) + return nil, nil +} + +// PreFilterExtensions returns prefilter extensions, pod add and remove. +func (pl *dynamicResources) PreFilterExtensions() framework.PreFilterExtensions { + return nil +} + +func getStateData(cs *framework.CycleState) (*stateData, error) { + state, err := cs.Read(stateKey) + if err != nil { + return nil, err + } + s, ok := state.(*stateData) + if !ok { + return nil, errors.New("unable to convert state into stateData") + } + return s, nil +} + +// Filter invoked at the filter extension point. +// It evaluates if a pod can fit due to the resources it requests, +// for both allocated and unallocated claims. +// +// For claims that are bound, then it checks that the node affinity is +// satisfied by the given node. +// +// For claims that are unbound, it checks whether the claim might get allocated +// for the node. +func (pl *dynamicResources) Filter(ctx context.Context, cs *framework.CycleState, pod *v1.Pod, nodeInfo *framework.NodeInfo) *framework.Status { + if !pl.enabled { + return nil + } + state, err := getStateData(cs) + if err != nil { + return statusError(klog.FromContext(ctx), err) + } + if len(state.claims) == 0 { + return nil + } + + logger := klog.FromContext(ctx) + node := nodeInfo.Node() + + var unavailableClaims []int + for index, claim := range state.claims { + logger.V(10).Info("filtering based on resource claims of the pod", "pod", klog.KObj(pod), "node", klog.KObj(node), "resourceclaim", klog.KObj(claim)) + switch { + case claim.Status.Allocation != nil: + if nodeSelector := state.availableOnNodes[index]; nodeSelector != nil { + if !nodeSelector.Match(node) { + logger.V(5).Info("AvailableOnNodes does not match", "pod", klog.KObj(pod), "node", klog.KObj(node), "resourceclaim", klog.KObj(claim)) + unavailableClaims = append(unavailableClaims, index) + } + } + case claim.Status.DeallocationRequested: + // We shouldn't get here. PreFilter already checked this. + return statusUnschedulable(logger, "resourceclaim must be reallocated", "pod", klog.KObj(pod), "node", klog.KObj(node), "resourceclaim", klog.KObj(claim)) + case claim.Spec.AllocationMode == resourcev1alpha1.AllocationModeWaitForFirstConsumer: + // The ResourceClass might have a node filter. This is + // useful for trimming the initial set of potential + // nodes before we ask the driver(s) for information + // about the specific pod. + class, err := pl.classLister.Get(claim.Spec.ResourceClassName) + if err != nil { + // If the class does not exist, then allocation cannot proceed. + return statusError(logger, fmt.Errorf("look up resource class: %v", err)) + } + if class.SuitableNodes != nil { + // TODO (#113700): parse class.SuitableNodes once in PreFilter, reuse result. + matches, err := corev1helpers.MatchNodeSelectorTerms(node, class.SuitableNodes) + if err != nil { + return statusError(logger, fmt.Errorf("potential node filter: %v", err)) + } + if !matches { + return statusUnschedulable(logger, "excluded by resource class node filter", "pod", klog.KObj(pod), "node", klog.KObj(node), "resourceclass", klog.KObj(class)) + } + } + + // Now we need information from drivers. + podScheduling, err := state.initializePodScheduling(ctx, pod, pl.podSchedulingLister) + if err != nil { + return statusError(logger, err) + } + status := statusForClaim(podScheduling, pod.Spec.ResourceClaims[index].Name) + if status != nil { + for _, unsuitableNode := range status.UnsuitableNodes { + if node.Name == unsuitableNode { + return statusUnschedulable(logger, "resourceclaim cannot be allocated for the node (unsuitable)", "pod", klog.KObj(pod), "node", klog.KObj(node), "resourceclaim", klog.KObj(claim), "unsuitablenodes", status.UnsuitableNodes) + } + } + } + default: + // This should have been delayed allocation. Immediate + // allocation was already checked for in PreFilter. + return statusError(logger, fmt.Errorf("internal error, unexpected allocation mode %v", claim.Spec.AllocationMode)) + } + } + + if len(unavailableClaims) > 0 { + state.mutex.Lock() + defer state.mutex.Unlock() + if state.unavailableClaims == nil { + state.unavailableClaims = sets.NewInt() + } + + for index := range unavailableClaims { + claim := state.claims[index] + // Deallocation makes more sense for claims with + // delayed allocation. Claims with immediate allocation + // would just get allocated again for a random node, + // which is unlikely to help the pod. + if claim.Spec.AllocationMode == resourcev1alpha1.AllocationModeWaitForFirstConsumer { + state.unavailableClaims.Insert(unavailableClaims...) + } + } + return statusUnschedulable(logger, "resourceclaim not available on the node", "pod", klog.KObj(pod)) + } + + return nil +} + +// PostFilter checks whether there are allocated claims that could get +// deallocated to help get the Pod schedulable. If yes, it picks one and +// requests its deallocation. This only gets called when filtering found no +// suitable node. +func (pl *dynamicResources) PostFilter(ctx context.Context, cs *framework.CycleState, pod *v1.Pod, filteredNodeStatusMap framework.NodeToStatusMap) (*framework.PostFilterResult, *framework.Status) { + if !pl.enabled { + return nil, framework.NewStatus(framework.Unschedulable, "plugin disabled") + } + logger := klog.FromContext(ctx) + state, err := getStateData(cs) + if err != nil { + return nil, statusError(logger, err) + } + if len(state.claims) == 0 { + return nil, framework.NewStatus(framework.Unschedulable, "no new claims to deallocate") + } + + // Iterating over a map is random. This is intentional here, we want to + // pick one claim randomly because there is no better heuristic. + for index := range state.unavailableClaims { + claim := state.claims[index] + if len(claim.Status.ReservedFor) == 0 || + len(claim.Status.ReservedFor) == 1 && claim.Status.ReservedFor[0].UID == pod.UID { + claim := state.claims[index].DeepCopy() + claim.Status.DeallocationRequested = true + claim.Status.ReservedFor = nil + logger.V(5).Info("Requesting deallocation of ResourceClaim", "pod", klog.KObj(pod), "resourceclaim", klog.KObj(claim)) + if err := state.updateClaimStatus(ctx, pl.clientset, index, claim); err != nil { + return nil, statusError(logger, err) + } + return nil, nil + } + } + return nil, framework.NewStatus(framework.Unschedulable, "still not schedulable") +} + +// PreScore is passed a list of all nodes that would fit the pod. Not all +// claims are necessarily allocated yet, so here we can set the SuitableNodes +// field for those which are pending. +func (pl *dynamicResources) PreScore(ctx context.Context, cs *framework.CycleState, pod *v1.Pod, nodes []*v1.Node) *framework.Status { + if !pl.enabled { + return nil + } + state, err := getStateData(cs) + if err != nil { + return statusError(klog.FromContext(ctx), err) + } + if len(state.claims) == 0 { + return nil + } + + logger := klog.FromContext(ctx) + podScheduling, err := state.initializePodScheduling(ctx, pod, pl.podSchedulingLister) + if err != nil { + return statusError(logger, err) + } + pending := false + for _, claim := range state.claims { + if claim.Status.Allocation == nil { + pending = true + } + } + if pending && !haveAllNodes(podScheduling.Spec.PotentialNodes, nodes) { + // Remember the potential nodes. The object will get created or + // updated in Reserve. This is both an optimization and + // covers the case that PreScore doesn't get called when there + // is only a single node. + logger.V(5).Info("remembering potential nodes", "pod", klog.KObj(pod), "potentialnodes", klog.KObjSlice(nodes)) + podScheduling = podScheduling.DeepCopy() + numNodes := len(nodes) + if numNodes > resourcev1alpha1.PodSchedulingNodeListMaxSize { + numNodes = resourcev1alpha1.PodSchedulingNodeListMaxSize + } + podScheduling.Spec.PotentialNodes = make([]string, 0, numNodes) + if numNodes == len(nodes) { + // Copy all node names. + for _, node := range nodes { + podScheduling.Spec.PotentialNodes = append(podScheduling.Spec.PotentialNodes, node.Name) + } + } else { + // Select a random subset of the nodes to comply with + // the PotentialNodes length limit. Randomization is + // done for us by Go which iterates over map entries + // randomly. + nodeNames := map[string]struct{}{} + for _, node := range nodes { + nodeNames[node.Name] = struct{}{} + } + for nodeName := range nodeNames { + if len(podScheduling.Spec.PotentialNodes) >= resourcev1alpha1.PodSchedulingNodeListMaxSize { + break + } + podScheduling.Spec.PotentialNodes = append(podScheduling.Spec.PotentialNodes, nodeName) + } + } + sort.Strings(podScheduling.Spec.PotentialNodes) + state.storePodScheduling(podScheduling) + } + logger.V(5).Info("all potential nodes already set", "pod", klog.KObj(pod), "potentialnodes", nodes) + return nil +} + +func haveAllNodes(nodeNames []string, nodes []*v1.Node) bool { + for _, node := range nodes { + if !haveNode(nodeNames, node.Name) { + return false + } + } + return true +} + +func haveNode(nodeNames []string, nodeName string) bool { + for _, n := range nodeNames { + if n == nodeName { + return true + } + } + return false +} + +// Reserve reserves claims for the pod. +func (pl *dynamicResources) Reserve(ctx context.Context, cs *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status { + if !pl.enabled { + return nil + } + state, err := getStateData(cs) + if err != nil { + return statusError(klog.FromContext(ctx), err) + } + if len(state.claims) == 0 { + return nil + } + + numDelayedAllocationPending := 0 + numClaimsWithStatusInfo := 0 + logger := klog.FromContext(ctx) + podScheduling, err := state.initializePodScheduling(ctx, pod, pl.podSchedulingLister) + if err != nil { + return statusError(logger, err) + } + for index, claim := range state.claims { + if claim.Status.Allocation != nil { + // Allocated, but perhaps not reserved yet. + if resourceclaim.IsReservedForPod(pod, claim) { + logger.V(5).Info("is reserved", "pod", klog.KObj(pod), "node", klog.ObjectRef{Name: nodeName}, "resourceclaim", klog.KObj(claim)) + continue + } + claim := claim.DeepCopy() + claim.Status.ReservedFor = append(claim.Status.ReservedFor, + resourcev1alpha1.ResourceClaimConsumerReference{ + Resource: "pods", + Name: pod.Name, + UID: pod.UID, + }) + logger.V(5).Info("reserve", "pod", klog.KObj(pod), "node", klog.ObjectRef{Name: nodeName}, "resourceclaim", klog.KObj(claim)) + _, err := pl.clientset.ResourceV1alpha1().ResourceClaims(claim.Namespace).UpdateStatus(ctx, claim, metav1.UpdateOptions{}) + // TODO: metric for update errors. + if err != nil { + return statusError(logger, err) + } + // If we get here, we know that reserving the claim for + // the pod worked and we can proceed with scheduling + // it. + } else { + // Must be delayed allocation. + numDelayedAllocationPending++ + + // Did the driver provide information that steered node + // selection towards a node that it can support? + if statusForClaim(podScheduling, pod.Spec.ResourceClaims[index].Name) != nil { + numClaimsWithStatusInfo++ + } + } + } + + if numDelayedAllocationPending == 0 { + // Nothing left to do. + return nil + } + + podSchedulingDirty := state.podSchedulingDirty + if len(podScheduling.Spec.PotentialNodes) == 0 { + // PreScore was not called, probably because there was + // only one candidate. We need to ask whether that + // node is suitable, otherwise the scheduler will pick + // it forever even when it cannot satisfy the claim. + podScheduling = podScheduling.DeepCopy() + podScheduling.Spec.PotentialNodes = []string{nodeName} + logger.V(5).Info("asking for information about single potential node", "pod", klog.KObj(pod), "node", klog.ObjectRef{Name: nodeName}) + podSchedulingDirty = true + } + + // When there is only one pending resource, we can go ahead with + // requesting allocation even when we don't have the information from + // the driver yet. Otherwise we wait for information before blindly + // making a decision that might have to be reversed later. + if numDelayedAllocationPending == 1 || numClaimsWithStatusInfo == numDelayedAllocationPending { + podScheduling = podScheduling.DeepCopy() + // TODO: can we increase the chance that the scheduler picks + // the same node as before when allocation is on-going, + // assuming that that node still fits the pod? Picking a + // different node may lead to some claims being allocated for + // one node and others for another, which then would have to be + // resolved with deallocation. + podScheduling.Spec.SelectedNode = nodeName + logger.V(5).Info("start allocation", "pod", klog.KObj(pod), "node", klog.ObjectRef{Name: nodeName}) + if err := state.publishPodScheduling(ctx, pl.clientset, podScheduling); err != nil { + return statusError(logger, err) + } + return statusUnschedulable(logger, "waiting for resource driver to allocate resource", "pod", klog.KObj(pod), "node", klog.ObjectRef{Name: nodeName}) + } + + // May have been modified earlier in PreScore or above. + if podSchedulingDirty { + if err := state.publishPodScheduling(ctx, pl.clientset, podScheduling); err != nil { + return statusError(logger, err) + } + } + + // More than one pending claim and not enough information about all of them. + // + // TODO: can or should we ensure that scheduling gets aborted while + // waiting for resources *before* triggering delayed volume + // provisioning? On the one hand, volume provisioning is currently + // irreversible, so it better should come last. On the other hand, + // triggering both in parallel might be faster. + return statusUnschedulable(logger, "waiting for resource driver to provide information", "pod", klog.KObj(pod)) +} + +// Unreserve clears the ReservedFor field for all claims. +// It's idempotent, and does nothing if no state found for the given pod. +func (pl *dynamicResources) Unreserve(ctx context.Context, cs *framework.CycleState, pod *v1.Pod, nodeName string) { + if !pl.enabled { + return + } + state, err := getStateData(cs) + if err != nil { + return + } + if len(state.claims) == 0 { + return + } + + logger := klog.FromContext(ctx) + for index, claim := range state.claims { + if claim.Status.Allocation != nil && + resourceclaim.IsReservedForPod(pod, claim) { + // Remove pod from ReservedFor. + claim := claim.DeepCopy() + reservedFor := make([]resourcev1alpha1.ResourceClaimConsumerReference, 0, len(claim.Status.ReservedFor)-1) + for _, reserved := range claim.Status.ReservedFor { + // TODO: can UID be assumed to be unique all resources or do we also need to compare Group/Version/Resource? + if reserved.UID != pod.UID { + reservedFor = append(reservedFor, reserved) + } + } + claim.Status.ReservedFor = reservedFor + logger.V(5).Info("unreserve", "resourceclaim", klog.KObj(claim)) + if err := state.updateClaimStatus(ctx, pl.clientset, index, claim); err != nil { + // We will get here again when pod scheduling + // is retried. + logger.Error(err, "unreserve", "resourceclaim", klog.KObj(claim)) + } + } + } +} + +// PostBind is called after a pod is successfully bound to a node. Now we are +// sure that a PodScheduling object, if it exists, is definitely not going to +// be needed anymore and can delete it. This is a one-shot thing, there won't +// be any retries. This is okay because it should usually work and in those +// cases where it doesn't, the garbage collector will eventually clean up. +func (pl *dynamicResources) PostBind(ctx context.Context, cs *framework.CycleState, pod *v1.Pod, nodeName string) { + if !pl.enabled { + return + } + state, err := getStateData(cs) + if err != nil { + return + } + if len(state.claims) == 0 { + return + } + + // We cannot know for sure whether the PodScheduling object exists. We + // might have created it in the previous pod scheduling cycle and not + // have it in our informer cache yet. Let's try to delete, just to be + // on the safe side. + logger := klog.FromContext(ctx) + err = pl.clientset.ResourceV1alpha1().PodSchedulings(pod.Namespace).Delete(ctx, pod.Name, metav1.DeleteOptions{}) + switch { + case apierrors.IsNotFound(err): + logger.V(5).Info("no PodScheduling object to delete") + case err != nil: + logger.Error(err, "delete PodScheduling") + default: + logger.V(5).Info("PodScheduling object deleted") + } +} + +// statusUnschedulable ensures that there is a log message associated with the +// line where the status originated. +func statusUnschedulable(logger klog.Logger, reason string, kv ...interface{}) *framework.Status { + if loggerV := logger.V(5); loggerV.Enabled() { + helper, loggerV := loggerV.WithCallStackHelper() + helper() + kv = append(kv, "reason", reason) + // nolint: logcheck // warns because it cannot check key/values + loggerV.Info("pod unschedulable", kv...) + } + return framework.NewStatus(framework.UnschedulableAndUnresolvable, reason) +} + +// statusError ensures that there is a log message associated with the +// line where the error originated. +func statusError(logger klog.Logger, err error, kv ...interface{}) *framework.Status { + if loggerV := logger.V(5); loggerV.Enabled() { + helper, loggerV := loggerV.WithCallStackHelper() + helper() + // nolint: logcheck // warns because it cannot check key/values + loggerV.Error(err, "dynamic resource plugin failed", kv...) + } + return framework.AsStatus(err) +} diff --git a/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources_test.go b/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources_test.go new file mode 100644 index 00000000000..2d135e8bf82 --- /dev/null +++ b/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources_test.go @@ -0,0 +1,789 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dynamicresources + +import ( + "context" + "errors" + "fmt" + "sort" + "sync" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + v1 "k8s.io/api/core/v1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apiruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes/fake" + cgotesting "k8s.io/client-go/testing" + "k8s.io/klog/v2/ktesting" + _ "k8s.io/klog/v2/ktesting/init" + "k8s.io/kubernetes/pkg/scheduler/framework" + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature" + "k8s.io/kubernetes/pkg/scheduler/framework/runtime" + st "k8s.io/kubernetes/pkg/scheduler/testing" +) + +var ( + podKind = v1.SchemeGroupVersion.WithKind("Pod") + + podName = "my-pod" + podUID = "1234" + resourceName = "my-resource" + resourceName2 = resourceName + "-2" + claimName = podName + "-" + resourceName + claimName2 = podName + "-" + resourceName + "-2" + className = "my-resource-class" + namespace = "default" + + resourceClass = &resourcev1alpha1.ResourceClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: className, + }, + DriverName: "some-driver", + } + + podWithClaimName = st.MakePod().Name(podName).Namespace(namespace). + UID(podUID). + PodResourceClaims(v1.PodResourceClaim{Name: resourceName, Source: v1.ClaimSource{ResourceClaimName: &claimName}}). + Obj() + otherPodWithClaimName = st.MakePod().Name(podName).Namespace(namespace). + UID(podUID + "-II"). + PodResourceClaims(v1.PodResourceClaim{Name: resourceName, Source: v1.ClaimSource{ResourceClaimName: &claimName}}). + Obj() + podWithClaimTemplate = st.MakePod().Name(podName).Namespace(namespace). + UID(podUID). + PodResourceClaims(v1.PodResourceClaim{Name: resourceName, Source: v1.ClaimSource{ResourceClaimTemplateName: &claimName}}). + Obj() + podWithTwoClaimNames = st.MakePod().Name(podName).Namespace(namespace). + UID(podUID). + PodResourceClaims(v1.PodResourceClaim{Name: resourceName, Source: v1.ClaimSource{ResourceClaimName: &claimName}}). + PodResourceClaims(v1.PodResourceClaim{Name: resourceName2, Source: v1.ClaimSource{ResourceClaimName: &claimName2}}). + Obj() + + workerNode = &st.MakeNode().Name("worker").Label("nodename", "worker").Node + + claim = st.MakeResourceClaim(). + Name(claimName). + Namespace(namespace). + ResourceClassName(className). + Obj() + pendingImmediateClaim = st.FromResourceClaim(claim). + AllocationMode(resourcev1alpha1.AllocationModeImmediate). + Obj() + pendingDelayedClaim = st.FromResourceClaim(claim). + AllocationMode(resourcev1alpha1.AllocationModeWaitForFirstConsumer). + Obj() + pendingDelayedClaim2 = st.FromResourceClaim(pendingDelayedClaim). + Name(claimName2). + Obj() + deallocatingClaim = st.FromResourceClaim(pendingImmediateClaim). + Allocation(&resourcev1alpha1.AllocationResult{}). + DeallocationRequested(true). + Obj() + inUseClaim = st.FromResourceClaim(pendingImmediateClaim). + Allocation(&resourcev1alpha1.AllocationResult{}). + ReservedFor(resourcev1alpha1.ResourceClaimConsumerReference{UID: types.UID(podUID)}). + Obj() + allocatedClaim = st.FromResourceClaim(pendingDelayedClaim). + OwnerReference(podName, podUID, podKind). + Allocation(&resourcev1alpha1.AllocationResult{}). + Obj() + allocatedDelayedClaimWithWrongTopology = st.FromResourceClaim(allocatedClaim). + Allocation(&resourcev1alpha1.AllocationResult{AvailableOnNodes: st.MakeNodeSelector().In("no-such-label", []string{"no-such-value"}).Obj()}). + Obj() + allocatedImmediateClaimWithWrongTopology = st.FromResourceClaim(allocatedDelayedClaimWithWrongTopology). + AllocationMode(resourcev1alpha1.AllocationModeImmediate). + Obj() + allocatedClaimWithGoodTopology = st.FromResourceClaim(allocatedClaim). + Allocation(&resourcev1alpha1.AllocationResult{AvailableOnNodes: st.MakeNodeSelector().In("nodename", []string{"worker"}).Obj()}). + Obj() + otherClaim = st.MakeResourceClaim(). + Name("not-my-claim"). + Namespace(namespace). + ResourceClassName(className). + Obj() + + scheduling = st.MakePodScheduling().Name(podName).Namespace(namespace). + OwnerReference(podName, podUID, podKind). + Obj() + schedulingPotential = st.FromPodScheduling(scheduling). + PotentialNodes(workerNode.Name). + Obj() + schedulingSelectedPotential = st.FromPodScheduling(schedulingPotential). + SelectedNode(workerNode.Name). + Obj() + schedulingInfo = st.FromPodScheduling(schedulingPotential). + ResourceClaims(resourcev1alpha1.ResourceClaimSchedulingStatus{Name: resourceName}, + resourcev1alpha1.ResourceClaimSchedulingStatus{Name: resourceName2}). + Obj() +) + +// result defines the expected outcome of some operation. It covers +// operation's status and the state of the world (= objects). +type result struct { + status *framework.Status + // changes contains a mapping of name to an update function for + // the corresponding object. These functions apply exactly the expected + // changes to a copy of the object as it existed before the operation. + changes change + + // added contains objects created by the operation. + added []metav1.Object + + // removed contains objects deleted by the operation. + removed []metav1.Object +} + +// change contains functions for modifying objects of a certain type. These +// functions will get called for all objects of that type. If they needs to +// make changes only to a particular instance, then it must check the name. +type change struct { + scheduling func(*resourcev1alpha1.PodScheduling) *resourcev1alpha1.PodScheduling + claim func(*resourcev1alpha1.ResourceClaim) *resourcev1alpha1.ResourceClaim +} +type perNodeResult map[string]result + +func (p perNodeResult) forNode(nodeName string) result { + if p == nil { + return result{} + } + return p[nodeName] +} + +type want struct { + preFilterResult *framework.PreFilterResult + prefilter result + filter perNodeResult + prescore result + reserve result + unreserve result + postbind result + postFilterResult *framework.PostFilterResult + postfilter result +} + +// prepare contains changes for objects in the API server. +// Those changes are applied before running the steps. This can +// be used to simulate concurrent changes by some other entities +// like a resource driver. +type prepare struct { + filter change + prescore change + reserve change + unreserve change + postbind change + postfilter change +} + +func TestPlugin(t *testing.T) { + testcases := map[string]struct { + nodes []*v1.Node // default if unset is workerNode + pod *v1.Pod + claims []*resourcev1alpha1.ResourceClaim + classes []*resourcev1alpha1.ResourceClass + schedulings []*resourcev1alpha1.PodScheduling + + prepare prepare + want want + }{ + "empty": { + pod: st.MakePod().Name("foo").Namespace("default").Obj(), + }, + "claim-reference": { + pod: podWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{allocatedClaim, otherClaim}, + }, + "claim-template": { + pod: podWithClaimTemplate, + claims: []*resourcev1alpha1.ResourceClaim{allocatedClaim, otherClaim}, + }, + "missing-claim": { + pod: podWithClaimTemplate, + want: want{ + prefilter: result{ + status: framework.NewStatus(framework.UnschedulableAndUnresolvable, `waiting for dynamic resource controller to create the resourceclaim "my-pod-my-resource"`), + }, + postfilter: result{ + status: framework.NewStatus(framework.Unschedulable, `no new claims to deallocate`), + }, + }, + }, + "waiting-for-immediate-allocation": { + pod: podWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{pendingImmediateClaim}, + want: want{ + prefilter: result{ + status: framework.NewStatus(framework.UnschedulableAndUnresolvable, `unallocated immediate resourceclaim`), + }, + postfilter: result{ + status: framework.NewStatus(framework.Unschedulable, `no new claims to deallocate`), + }, + }, + }, + "waiting-for-deallocation": { + pod: podWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{deallocatingClaim}, + want: want{ + prefilter: result{ + status: framework.NewStatus(framework.UnschedulableAndUnresolvable, `resourceclaim must be reallocated`), + }, + postfilter: result{ + status: framework.NewStatus(framework.Unschedulable, `no new claims to deallocate`), + }, + }, + }, + "delayed-allocation-missing-class": { + pod: podWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{pendingDelayedClaim}, + want: want{ + filter: perNodeResult{ + workerNode.Name: { + status: framework.AsStatus(fmt.Errorf(`look up resource class: resourceclass.resource.k8s.io "%s" not found`, className)), + }, + }, + postfilter: result{ + status: framework.NewStatus(framework.Unschedulable, `still not schedulable`), + }, + }, + }, + "delayed-allocation-scheduling-select-immediately": { + // Create the PodScheduling object, ask for information + // and select a node. + pod: podWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{pendingDelayedClaim}, + classes: []*resourcev1alpha1.ResourceClass{resourceClass}, + want: want{ + reserve: result{ + status: framework.NewStatus(framework.UnschedulableAndUnresolvable, `waiting for resource driver to allocate resource`), + added: []metav1.Object{schedulingSelectedPotential}, + }, + }, + }, + "delayed-allocation-scheduling-ask": { + // Create the PodScheduling object, ask for + // information, but do not select a node because + // there are multiple claims. + pod: podWithTwoClaimNames, + claims: []*resourcev1alpha1.ResourceClaim{pendingDelayedClaim, pendingDelayedClaim2}, + classes: []*resourcev1alpha1.ResourceClass{resourceClass}, + want: want{ + reserve: result{ + status: framework.NewStatus(framework.UnschedulableAndUnresolvable, `waiting for resource driver to provide information`), + added: []metav1.Object{schedulingPotential}, + }, + }, + }, + "delayed-allocation-scheduling-finish": { + // Use the populated PodScheduling object to select a + // node. + pod: podWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{pendingDelayedClaim}, + schedulings: []*resourcev1alpha1.PodScheduling{schedulingInfo}, + classes: []*resourcev1alpha1.ResourceClass{resourceClass}, + want: want{ + reserve: result{ + status: framework.NewStatus(framework.UnschedulableAndUnresolvable, `waiting for resource driver to allocate resource`), + changes: change{ + scheduling: func(in *resourcev1alpha1.PodScheduling) *resourcev1alpha1.PodScheduling { + return st.FromPodScheduling(in). + SelectedNode(workerNode.Name). + Obj() + }, + }, + }, + }, + }, + "delayed-allocation-scheduling-finish-concurrent-label-update": { + // Use the populated PodScheduling object to select a + // node. + pod: podWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{pendingDelayedClaim}, + schedulings: []*resourcev1alpha1.PodScheduling{schedulingInfo}, + classes: []*resourcev1alpha1.ResourceClass{resourceClass}, + prepare: prepare{ + reserve: change{ + scheduling: func(in *resourcev1alpha1.PodScheduling) *resourcev1alpha1.PodScheduling { + // This does not actually conflict with setting the + // selected node, but because the plugin is not using + // patching yet, Update nonetheless fails. + return st.FromPodScheduling(in). + Label("hello", "world"). + Obj() + }, + }, + }, + want: want{ + reserve: result{ + status: framework.AsStatus(errors.New(`ResourceVersion must match the object that gets updated`)), + }, + }, + }, + "delayed-allocation-scheduling-completed": { + // Remove PodScheduling object once the pod is scheduled. + pod: podWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{allocatedClaim}, + schedulings: []*resourcev1alpha1.PodScheduling{schedulingInfo}, + classes: []*resourcev1alpha1.ResourceClass{resourceClass}, + want: want{ + reserve: result{ + changes: change{ + claim: func(in *resourcev1alpha1.ResourceClaim) *resourcev1alpha1.ResourceClaim { + return st.FromResourceClaim(in). + ReservedFor(resourcev1alpha1.ResourceClaimConsumerReference{Resource: "pods", Name: podName, UID: types.UID(podUID)}). + Obj() + }, + }, + }, + postbind: result{ + removed: []metav1.Object{schedulingInfo}, + }, + }, + }, + "in-use-by-other": { + nodes: []*v1.Node{}, + pod: otherPodWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{inUseClaim}, + classes: []*resourcev1alpha1.ResourceClass{}, + schedulings: []*resourcev1alpha1.PodScheduling{}, + prepare: prepare{}, + want: want{ + prefilter: result{ + status: framework.NewStatus(framework.UnschedulableAndUnresolvable, `resourceclaim in use`), + }, + postfilter: result{ + status: framework.NewStatus(framework.Unschedulable, `no new claims to deallocate`), + }, + }, + }, + "wrong-topology-delayed-allocation": { + // PostFilter tries to get the pod scheduleable by + // deallocating the claim. + pod: podWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{allocatedDelayedClaimWithWrongTopology}, + want: want{ + filter: perNodeResult{ + workerNode.Name: { + status: framework.NewStatus(framework.UnschedulableAndUnresolvable, `resourceclaim not available on the node`), + }, + }, + postfilter: result{ + // Claims with delayed allocation get deallocated. + changes: change{ + claim: func(in *resourcev1alpha1.ResourceClaim) *resourcev1alpha1.ResourceClaim { + return st.FromResourceClaim(in). + DeallocationRequested(true). + Obj() + }, + }, + }, + }, + }, + "wrong-topology-immediate-allocation": { + // PostFilter tries to get the pod scheduleable by + // deallocating the claim. + pod: podWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{allocatedImmediateClaimWithWrongTopology}, + want: want{ + filter: perNodeResult{ + workerNode.Name: { + status: framework.NewStatus(framework.UnschedulableAndUnresolvable, `resourceclaim not available on the node`), + }, + }, + postfilter: result{ + // Claims with immediate allocation don't. They would just get allocated again right + // away, without considering the needs of the pod. + status: framework.NewStatus(framework.Unschedulable, `still not schedulable`), + }, + }, + }, + "good-topology": { + pod: podWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{allocatedClaimWithGoodTopology}, + want: want{ + reserve: result{ + changes: change{ + claim: func(in *resourcev1alpha1.ResourceClaim) *resourcev1alpha1.ResourceClaim { + return st.FromResourceClaim(in). + ReservedFor(resourcev1alpha1.ResourceClaimConsumerReference{Resource: "pods", Name: podName, UID: types.UID(podUID)}). + Obj() + }, + }, + }, + }, + }, + "reserved-okay": { + pod: podWithClaimName, + claims: []*resourcev1alpha1.ResourceClaim{inUseClaim}, + }, + } + + for name, tc := range testcases { + // We can run in parallel because logging is per-test. + tc := tc + t.Run(name, func(t *testing.T) { + t.Parallel() + nodes := tc.nodes + if nodes == nil { + nodes = []*v1.Node{workerNode} + } + testCtx := setup(t, nodes, tc.claims, tc.classes, tc.schedulings) + + initialObjects := testCtx.listAll(t) + result, status := testCtx.p.PreFilter(testCtx.ctx, testCtx.state, tc.pod) + t.Run("prefilter", func(t *testing.T) { + assert.Equal(t, tc.want.preFilterResult, result) + testCtx.verify(t, tc.want.prefilter, initialObjects, result, status) + }) + unschedulable := status.Code() != framework.Success + + var potentialNodes []*v1.Node + + initialObjects = testCtx.listAll(t) + testCtx.updateAPIServer(t, initialObjects, tc.prepare.filter) + if !unschedulable { + for _, nodeInfo := range testCtx.nodeInfos { + initialObjects = testCtx.listAll(t) + status := testCtx.p.Filter(testCtx.ctx, testCtx.state, tc.pod, nodeInfo) + nodeName := nodeInfo.Node().Name + t.Run(fmt.Sprintf("filter/%s", nodeInfo.Node().Name), func(t *testing.T) { + testCtx.verify(t, tc.want.filter.forNode(nodeName), initialObjects, nil, status) + }) + if status.Code() != framework.Success { + unschedulable = true + } else { + potentialNodes = append(potentialNodes, nodeInfo.Node()) + } + } + } + + if !unschedulable && len(potentialNodes) > 0 { + initialObjects = testCtx.listAll(t) + initialObjects = testCtx.updateAPIServer(t, initialObjects, tc.prepare.prescore) + status := testCtx.p.PreScore(testCtx.ctx, testCtx.state, tc.pod, potentialNodes) + t.Run("prescore", func(t *testing.T) { + testCtx.verify(t, tc.want.prescore, initialObjects, nil, status) + }) + if status.Code() != framework.Success { + unschedulable = true + } + } + + var selectedNode *v1.Node + if !unschedulable && len(potentialNodes) > 0 { + selectedNode = potentialNodes[0] + + initialObjects = testCtx.listAll(t) + initialObjects = testCtx.updateAPIServer(t, initialObjects, tc.prepare.reserve) + status := testCtx.p.Reserve(testCtx.ctx, testCtx.state, tc.pod, selectedNode.Name) + t.Run("reserve", func(t *testing.T) { + testCtx.verify(t, tc.want.reserve, initialObjects, nil, status) + }) + if status.Code() != framework.Success { + unschedulable = true + } + } + + if selectedNode != nil { + if unschedulable { + initialObjects = testCtx.listAll(t) + initialObjects = testCtx.updateAPIServer(t, initialObjects, tc.prepare.unreserve) + testCtx.p.Unreserve(testCtx.ctx, testCtx.state, tc.pod, selectedNode.Name) + t.Run("unreserve", func(t *testing.T) { + testCtx.verify(t, tc.want.unreserve, initialObjects, nil, status) + }) + } else { + initialObjects = testCtx.listAll(t) + initialObjects = testCtx.updateAPIServer(t, initialObjects, tc.prepare.postbind) + testCtx.p.PostBind(testCtx.ctx, testCtx.state, tc.pod, selectedNode.Name) + t.Run("postbind", func(t *testing.T) { + testCtx.verify(t, tc.want.postbind, initialObjects, nil, status) + }) + } + } else { + initialObjects = testCtx.listAll(t) + initialObjects = testCtx.updateAPIServer(t, initialObjects, tc.prepare.postfilter) + result, status := testCtx.p.PostFilter(testCtx.ctx, testCtx.state, tc.pod, nil /* filteredNodeStatusMap not used by plugin */) + t.Run("postfilter", func(t *testing.T) { + assert.Equal(t, tc.want.postFilterResult, result) + testCtx.verify(t, tc.want.postfilter, initialObjects, nil, status) + }) + } + }) + } +} + +type testContext struct { + ctx context.Context + client *fake.Clientset + p *dynamicResources + nodeInfos []*framework.NodeInfo + state *framework.CycleState +} + +func (tc *testContext) verify(t *testing.T, expected result, initialObjects []metav1.Object, result interface{}, status *framework.Status) { + t.Helper() + assert.Equal(t, expected.status, status) + objects := tc.listAll(t) + wantObjects := update(t, initialObjects, expected.changes) + for _, add := range expected.added { + wantObjects = append(wantObjects, add) + } + for _, remove := range expected.removed { + for i, obj := range wantObjects { + // This is a bit relaxed (no GVR comparison, no UID + // comparison) to simplify writing the test cases. + if obj.GetName() == remove.GetName() && obj.GetNamespace() == remove.GetNamespace() { + wantObjects = append(wantObjects[0:i], wantObjects[i+1:]...) + break + } + } + } + sortObjects(wantObjects) + stripObjects(wantObjects) + stripObjects(objects) + assert.Equal(t, wantObjects, objects) +} + +// setGVK is implemented by metav1.TypeMeta and thus all API objects, in +// contrast to metav1.Type, which is not (?!) implemented. +type setGVK interface { + SetGroupVersionKind(gvk schema.GroupVersionKind) +} + +// stripObjects removes certain fields (Kind, APIVersion, etc.) which are not +// important and might not be set. +func stripObjects(objects []metav1.Object) { + for _, obj := range objects { + obj.SetResourceVersion("") + obj.SetUID("") + if objType, ok := obj.(setGVK); ok { + objType.SetGroupVersionKind(schema.GroupVersionKind{}) + } + } +} + +func (tc *testContext) listAll(t *testing.T) (objects []metav1.Object) { + t.Helper() + claims, err := tc.client.ResourceV1alpha1().ResourceClaims("").List(tc.ctx, metav1.ListOptions{}) + require.NoError(t, err, "list claims") + for _, claim := range claims.Items { + objects = append(objects, &claim) + } + schedulings, err := tc.client.ResourceV1alpha1().PodSchedulings("").List(tc.ctx, metav1.ListOptions{}) + require.NoError(t, err, "list pod scheduling") + for _, scheduling := range schedulings.Items { + objects = append(objects, &scheduling) + } + + sortObjects(objects) + return +} + +// updateAPIServer modifies objects and stores any changed object in the API server. +func (tc *testContext) updateAPIServer(t *testing.T, objects []metav1.Object, updates change) []metav1.Object { + modified := update(t, objects, updates) + for i := range modified { + obj := modified[i] + if diff := cmp.Diff(objects[i], obj); diff != "" { + t.Logf("Updating %T %q, diff (-old, +new):\n%s", obj, obj.GetName(), diff) + switch obj := obj.(type) { + case *resourcev1alpha1.ResourceClaim: + obj, err := tc.client.ResourceV1alpha1().ResourceClaims(obj.Namespace).Update(tc.ctx, obj, metav1.UpdateOptions{}) + if err != nil { + t.Fatalf("unexpected error during prepare update: %v", err) + } + modified[i] = obj + case *resourcev1alpha1.PodScheduling: + obj, err := tc.client.ResourceV1alpha1().PodSchedulings(obj.Namespace).Update(tc.ctx, obj, metav1.UpdateOptions{}) + if err != nil { + t.Fatalf("unexpected error during prepare update: %v", err) + } + modified[i] = obj + default: + t.Fatalf("unsupported object type %T", obj) + } + } + } + return modified +} + +func sortObjects(objects []metav1.Object) { + sort.Slice(objects, func(i, j int) bool { + if objects[i].GetNamespace() < objects[j].GetNamespace() { + return true + } + return objects[i].GetName() < objects[j].GetName() + }) +} + +// update walks through all existing objects, finds the corresponding update +// function based on name and kind, and replaces those objects that have an +// update function. The rest is left unchanged. +func update(t *testing.T, objects []metav1.Object, updates change) []metav1.Object { + var updated []metav1.Object + + for _, obj := range objects { + switch in := obj.(type) { + case *resourcev1alpha1.ResourceClaim: + if updates.claim != nil { + obj = updates.claim(in) + } + case *resourcev1alpha1.PodScheduling: + if updates.scheduling != nil { + obj = updates.scheduling(in) + } + } + updated = append(updated, obj) + } + + return updated +} + +func setup(t *testing.T, nodes []*v1.Node, claims []*resourcev1alpha1.ResourceClaim, classes []*resourcev1alpha1.ResourceClass, schedulings []*resourcev1alpha1.PodScheduling) (result *testContext) { + t.Helper() + + tc := &testContext{} + _, ctx := ktesting.NewTestContext(t) + ctx, cancel := context.WithCancel(ctx) + t.Cleanup(cancel) + tc.ctx = ctx + + tc.client = fake.NewSimpleClientset() + reactor := createReactor(tc.client.Tracker()) + tc.client.PrependReactor("*", "*", reactor) + + informerFactory := informers.NewSharedInformerFactory(tc.client, 0) + + opts := []runtime.Option{ + runtime.WithClientSet(tc.client), + runtime.WithInformerFactory(informerFactory), + } + fh, err := runtime.NewFramework(nil, nil, tc.ctx.Done(), opts...) + if err != nil { + t.Fatal(err) + } + + pl, err := New(nil, fh, feature.Features{EnableDynamicResourceAllocation: true}) + if err != nil { + t.Fatal(err) + } + tc.p = pl.(*dynamicResources) + + // The tests use the API to create the objects because then reactors + // get triggered. + for _, claim := range claims { + _, err := tc.client.ResourceV1alpha1().ResourceClaims(claim.Namespace).Create(tc.ctx, claim, metav1.CreateOptions{}) + require.NoError(t, err, "create resource claim") + } + for _, class := range classes { + _, err := tc.client.ResourceV1alpha1().ResourceClasses().Create(tc.ctx, class, metav1.CreateOptions{}) + require.NoError(t, err, "create resource class") + } + for _, scheduling := range schedulings { + _, err := tc.client.ResourceV1alpha1().PodSchedulings(scheduling.Namespace).Create(tc.ctx, scheduling, metav1.CreateOptions{}) + require.NoError(t, err, "create pod scheduling") + } + + informerFactory.Start(tc.ctx.Done()) + t.Cleanup(func() { + // Need to cancel before waiting for the shutdown. + cancel() + // Now we can wait for all goroutines to stop. + informerFactory.Shutdown() + }) + + informerFactory.WaitForCacheSync(tc.ctx.Done()) + + for _, node := range nodes { + nodeInfo := framework.NewNodeInfo() + nodeInfo.SetNode(node) + tc.nodeInfos = append(tc.nodeInfos, nodeInfo) + } + tc.state = framework.NewCycleState() + + return tc +} + +// createReactor implements the logic required for the UID and ResourceVersion +// fields to work when using the fake client. Add it with client.PrependReactor +// to your fake client. ResourceVersion handling is required for conflict +// detection during updates, which is covered by some scenarios. +func createReactor(tracker cgotesting.ObjectTracker) func(action cgotesting.Action) (handled bool, ret apiruntime.Object, err error) { + var uidCounter int + var resourceVersionCounter int + var mutex sync.Mutex + + return func(action cgotesting.Action) (handled bool, ret apiruntime.Object, err error) { + createAction, ok := action.(cgotesting.CreateAction) + if !ok { + return false, nil, nil + } + obj, ok := createAction.GetObject().(metav1.Object) + if !ok { + return false, nil, nil + } + + mutex.Lock() + defer mutex.Unlock() + switch action.GetVerb() { + case "create": + if obj.GetUID() != "" { + return true, nil, errors.New("UID must not be set on create") + } + if obj.GetResourceVersion() != "" { + return true, nil, errors.New("ResourceVersion must not be set on create") + } + obj.SetUID(types.UID(fmt.Sprintf("UID-%d", uidCounter))) + uidCounter++ + obj.SetResourceVersion(fmt.Sprintf("REV-%d", resourceVersionCounter)) + resourceVersionCounter++ + case "update": + uid := obj.GetUID() + resourceVersion := obj.GetResourceVersion() + if uid == "" { + return true, nil, errors.New("UID must be set on update") + } + if resourceVersion == "" { + return true, nil, errors.New("ResourceVersion must be set on update") + } + + oldObj, err := tracker.Get(action.GetResource(), obj.GetNamespace(), obj.GetName()) + if err != nil { + return true, nil, err + } + oldObjMeta, ok := oldObj.(metav1.Object) + if !ok { + return true, nil, errors.New("internal error: unexpected old object type") + } + if oldObjMeta.GetResourceVersion() != resourceVersion { + return true, nil, errors.New("ResourceVersion must match the object that gets updated") + } + + obj.SetResourceVersion(fmt.Sprintf("REV-%d", resourceVersionCounter)) + resourceVersionCounter++ + } + return false, nil, nil + } +} diff --git a/pkg/scheduler/framework/plugins/feature/feature.go b/pkg/scheduler/framework/plugins/feature/feature.go index 48cd00b7abe..e0790a681ca 100644 --- a/pkg/scheduler/framework/plugins/feature/feature.go +++ b/pkg/scheduler/framework/plugins/feature/feature.go @@ -20,6 +20,7 @@ package feature // This struct allows us to break the dependency of the plugins on // the internal k8s features pkg. type Features struct { + EnableDynamicResourceAllocation bool EnableReadWriteOncePod bool EnableVolumeCapacityPriority bool EnableMinDomainsInPodTopologySpread bool diff --git a/pkg/scheduler/framework/plugins/names/names.go b/pkg/scheduler/framework/plugins/names/names.go index 11cc90e6392..3741f0a100a 100644 --- a/pkg/scheduler/framework/plugins/names/names.go +++ b/pkg/scheduler/framework/plugins/names/names.go @@ -20,6 +20,7 @@ const ( PrioritySort = "PrioritySort" DefaultBinder = "DefaultBinder" DefaultPreemption = "DefaultPreemption" + DynamicResources = "DynamicResources" ImageLocality = "ImageLocality" InterPodAffinity = "InterPodAffinity" NodeAffinity = "NodeAffinity" diff --git a/pkg/scheduler/framework/plugins/registry.go b/pkg/scheduler/framework/plugins/registry.go index 7605cd3c2a7..5769aee6e12 100644 --- a/pkg/scheduler/framework/plugins/registry.go +++ b/pkg/scheduler/framework/plugins/registry.go @@ -21,6 +21,7 @@ import ( "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultpreemption" + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/dynamicresources" plfeature "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/imagelocality" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity" @@ -46,6 +47,7 @@ import ( // through the WithFrameworkOutOfTreeRegistry option. func NewInTreeRegistry() runtime.Registry { fts := plfeature.Features{ + EnableDynamicResourceAllocation: feature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation), EnableReadWriteOncePod: feature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod), EnableVolumeCapacityPriority: feature.DefaultFeatureGate.Enabled(features.VolumeCapacityPriority), EnableMinDomainsInPodTopologySpread: feature.DefaultFeatureGate.Enabled(features.MinDomainsInPodTopologySpread), @@ -54,7 +56,8 @@ func NewInTreeRegistry() runtime.Registry { EnablePodSchedulingReadiness: feature.DefaultFeatureGate.Enabled(features.PodSchedulingReadiness), } - return runtime.Registry{ + registry := runtime.Registry{ + dynamicresources.Name: runtime.FactoryAdapter(fts, dynamicresources.New), selectorspread.Name: selectorspread.New, imagelocality.Name: imagelocality.New, tainttoleration.Name: tainttoleration.New, @@ -79,4 +82,6 @@ func NewInTreeRegistry() runtime.Registry { defaultpreemption.Name: runtime.FactoryAdapter(fts, defaultpreemption.New), schedulinggates.Name: runtime.FactoryAdapter(fts, schedulinggates.New), } + + return registry } diff --git a/pkg/scheduler/framework/types.go b/pkg/scheduler/framework/types.go index 420aa8a73d5..8e647fea466 100644 --- a/pkg/scheduler/framework/types.go +++ b/pkg/scheduler/framework/types.go @@ -64,6 +64,8 @@ const ( Node GVK = "Node" PersistentVolume GVK = "PersistentVolume" PersistentVolumeClaim GVK = "PersistentVolumeClaim" + PodScheduling GVK = "PodScheduling" + ResourceClaim GVK = "ResourceClaim" StorageClass GVK = "storage.k8s.io/StorageClass" CSINode GVK = "storage.k8s.io/CSINode" CSIDriver GVK = "storage.k8s.io/CSIDriver" diff --git a/pkg/scheduler/testing/wrappers.go b/pkg/scheduler/testing/wrappers.go index 991ba9f1250..f632c42ebd7 100644 --- a/pkg/scheduler/testing/wrappers.go +++ b/pkg/scheduler/testing/wrappers.go @@ -20,6 +20,7 @@ import ( "fmt" v1 "k8s.io/api/core/v1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -249,6 +250,12 @@ func (p *PodWrapper) Containers(containers []v1.Container) *PodWrapper { return p } +// PodResourceClaims appends PodResourceClaims into PodSpec of the inner pod. +func (p *PodWrapper) PodResourceClaims(podResourceClaims ...v1.PodResourceClaim) *PodWrapper { + p.Spec.ResourceClaims = append(p.Spec.ResourceClaims, podResourceClaims...) + return p +} + // Priority sets a priority value into PodSpec of the inner pod. func (p *PodWrapper) Priority(val int32) *PodWrapper { p.Spec.Priority = &val @@ -791,3 +798,160 @@ func (p *PersistentVolumeWrapper) HostPathVolumeSource(src *v1.HostPathVolumeSou p.PersistentVolume.Spec.HostPath = src return p } + +// ResourceClaimWrapper wraps a ResourceClaim inside. +type ResourceClaimWrapper struct{ resourcev1alpha1.ResourceClaim } + +// MakeResourceClaim creates a ResourceClaim wrapper. +func MakeResourceClaim() *ResourceClaimWrapper { + return &ResourceClaimWrapper{resourcev1alpha1.ResourceClaim{}} +} + +// FromResourceClaim creates a ResourceClaim wrapper from some existing object. +func FromResourceClaim(other *resourcev1alpha1.ResourceClaim) *ResourceClaimWrapper { + return &ResourceClaimWrapper{*other.DeepCopy()} +} + +// Obj returns the inner ResourceClaim. +func (wrapper *ResourceClaimWrapper) Obj() *resourcev1alpha1.ResourceClaim { + return &wrapper.ResourceClaim +} + +// Name sets `s` as the name of the inner object. +func (wrapper *ResourceClaimWrapper) Name(s string) *ResourceClaimWrapper { + wrapper.SetName(s) + return wrapper +} + +// UID sets `s` as the UID of the inner object. +func (wrapper *ResourceClaimWrapper) UID(s string) *ResourceClaimWrapper { + wrapper.SetUID(types.UID(s)) + return wrapper +} + +// Namespace sets `s` as the namespace of the inner object. +func (wrapper *ResourceClaimWrapper) Namespace(s string) *ResourceClaimWrapper { + wrapper.SetNamespace(s) + return wrapper +} + +// OwnerReference updates the owning controller of the object. +func (wrapper *ResourceClaimWrapper) OwnerReference(name, uid string, gvk schema.GroupVersionKind) *ResourceClaimWrapper { + wrapper.OwnerReferences = []metav1.OwnerReference{ + { + APIVersion: gvk.GroupVersion().String(), + Kind: gvk.Kind, + Name: name, + UID: types.UID(uid), + Controller: pointer.Bool(true), + }, + } + return wrapper +} + +// AllocationMode sets the allocation mode of the inner object. +func (wrapper *ResourceClaimWrapper) AllocationMode(a resourcev1alpha1.AllocationMode) *ResourceClaimWrapper { + wrapper.ResourceClaim.Spec.AllocationMode = a + return wrapper +} + +// ResourceClassName sets the resource class name of the inner object. +func (wrapper *ResourceClaimWrapper) ResourceClassName(name string) *ResourceClaimWrapper { + wrapper.ResourceClaim.Spec.ResourceClassName = name + return wrapper +} + +// Allocation sets the allocation of the inner object. +func (wrapper *ResourceClaimWrapper) Allocation(allocation *resourcev1alpha1.AllocationResult) *ResourceClaimWrapper { + wrapper.ResourceClaim.Status.Allocation = allocation + return wrapper +} + +// DeallocationRequested sets that field of the inner object. +func (wrapper *ResourceClaimWrapper) DeallocationRequested(deallocationRequested bool) *ResourceClaimWrapper { + wrapper.ResourceClaim.Status.DeallocationRequested = deallocationRequested + return wrapper +} + +// ReservedFor sets that field of the inner object. +func (wrapper *ResourceClaimWrapper) ReservedFor(consumers ...resourcev1alpha1.ResourceClaimConsumerReference) *ResourceClaimWrapper { + wrapper.ResourceClaim.Status.ReservedFor = consumers + return wrapper +} + +// PodSchedulingWrapper wraps a PodScheduling inside. +type PodSchedulingWrapper struct{ resourcev1alpha1.PodScheduling } + +// MakePodScheduling creates a PodScheduling wrapper. +func MakePodScheduling() *PodSchedulingWrapper { + return &PodSchedulingWrapper{resourcev1alpha1.PodScheduling{}} +} + +// FromPodScheduling creates a PodScheduling wrapper from some existing object. +func FromPodScheduling(other *resourcev1alpha1.PodScheduling) *PodSchedulingWrapper { + return &PodSchedulingWrapper{*other.DeepCopy()} +} + +// Obj returns the inner object. +func (wrapper *PodSchedulingWrapper) Obj() *resourcev1alpha1.PodScheduling { + return &wrapper.PodScheduling +} + +// Name sets `s` as the name of the inner object. +func (wrapper *PodSchedulingWrapper) Name(s string) *PodSchedulingWrapper { + wrapper.SetName(s) + return wrapper +} + +// UID sets `s` as the UID of the inner object. +func (wrapper *PodSchedulingWrapper) UID(s string) *PodSchedulingWrapper { + wrapper.SetUID(types.UID(s)) + return wrapper +} + +// Namespace sets `s` as the namespace of the inner object. +func (wrapper *PodSchedulingWrapper) Namespace(s string) *PodSchedulingWrapper { + wrapper.SetNamespace(s) + return wrapper +} + +// OwnerReference updates the owning controller of the inner object. +func (wrapper *PodSchedulingWrapper) OwnerReference(name, uid string, gvk schema.GroupVersionKind) *PodSchedulingWrapper { + wrapper.OwnerReferences = []metav1.OwnerReference{ + { + APIVersion: gvk.GroupVersion().String(), + Kind: gvk.Kind, + Name: name, + UID: types.UID(uid), + Controller: pointer.Bool(true), + }, + } + return wrapper +} + +// Label applies a {k,v} label pair to the inner object +func (wrapper *PodSchedulingWrapper) Label(k, v string) *PodSchedulingWrapper { + if wrapper.Labels == nil { + wrapper.Labels = make(map[string]string) + } + wrapper.Labels[k] = v + return wrapper +} + +// SelectedNode sets that field of the inner object. +func (wrapper *PodSchedulingWrapper) SelectedNode(s string) *PodSchedulingWrapper { + wrapper.Spec.SelectedNode = s + return wrapper +} + +// PotentialNodes sets that field of the inner object. +func (wrapper *PodSchedulingWrapper) PotentialNodes(nodes ...string) *PodSchedulingWrapper { + wrapper.Spec.PotentialNodes = nodes + return wrapper +} + +// ResourceClaims sets that field of the inner object. +func (wrapper *PodSchedulingWrapper) ResourceClaims(statuses ...resourcev1alpha1.ResourceClaimSchedulingStatus) *PodSchedulingWrapper { + wrapper.Status.ResourceClaims = statuses + return wrapper +} diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go index a0e93659f63..cbae6c311aa 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go @@ -205,6 +205,19 @@ func buildControllerRoles() ([]rbacv1.ClusterRole, []rbacv1.ClusterRoleBinding) }, }) + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) { + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "resource-claim-controller"}, + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("pods/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "create").Groups(resourceGroup).Resources("resourceclaims").RuleOrDie(), + rbacv1helpers.NewRule("update", "patch").Groups(resourceGroup).Resources("resourceclaims/status").RuleOrDie(), + eventsRule(), + }, + }) + } + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "generic-garbage-collector"}, Rules: []rbacv1.PolicyRule{ diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go index 85ef7b414f0..d0c023da03d 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go @@ -54,6 +54,7 @@ const ( extensionsGroup = "extensions" policyGroup = "policy" rbacGroup = "rbac.authorization.k8s.io" + resourceGroup = "resource.k8s.io" storageGroup = "storage.k8s.io" resMetricsGroup = "metrics.k8s.io" customMetricsGroup = "custom.metrics.k8s.io" @@ -174,6 +175,12 @@ func NodeRules() []rbacv1.PolicyRule { // RuntimeClass nodePolicyRules = append(nodePolicyRules, rbacv1helpers.NewRule("get", "list", "watch").Groups("node.k8s.io").Resources("runtimeclasses").RuleOrDie()) + + // DRA Resource Claims + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) { + nodePolicyRules = append(nodePolicyRules, rbacv1helpers.NewRule("get").Groups(resourceGroup).Resources("resourceclaims").RuleOrDie()) + } + return nodePolicyRules } @@ -563,6 +570,15 @@ func ClusterRoles() []rbacv1.ClusterRole { rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("csidrivers").RuleOrDie(), rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("csistoragecapacities").RuleOrDie(), } + // Needed for dynamic resource allocation. + if utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) { + kubeSchedulerRules = append(kubeSchedulerRules, + rbacv1helpers.NewRule(Read...).Groups(resourceGroup).Resources("resourceclaims", "resourceclasses").RuleOrDie(), + rbacv1helpers.NewRule(ReadUpdate...).Groups(resourceGroup).Resources("resourceclaims/status").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(resourceGroup).Resources("podschedulings").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(resourceGroup).Resources("podschedulings/status").RuleOrDie(), + ) + } roles = append(roles, rbacv1.ClusterRole{ // a role to use for the kube-scheduler ObjectMeta: metav1.ObjectMeta{Name: "system:kube-scheduler"}, diff --git a/staging/publishing/import-restrictions.yaml b/staging/publishing/import-restrictions.yaml index 95cc8906298..9b902f978fe 100644 --- a/staging/publishing/import-restrictions.yaml +++ b/staging/publishing/import-restrictions.yaml @@ -239,6 +239,16 @@ - k8s.io/klog - k8s.io/utils +- baseImportPath: "./vendor/k8s.io/dynamic-resource-allocation/" + allowedImports: + - k8s.io/api + - k8s.io/apimachinery + - k8s.io/client-go + - k8s.io/dynamic-resource-allocation + - k8s.io/klog + - k8s.io/kubelet + - k8s.io/utils + - baseImportPath: "./vendor/k8s.io/legacy-cloud-providers/" allowedImports: - k8s.io/api diff --git a/staging/publishing/rules.yaml b/staging/publishing/rules.yaml index ceaa9706ebf..cae8239bc57 100644 --- a/staging/publishing/rules.yaml +++ b/staging/publishing/rules.yaml @@ -1990,6 +1990,23 @@ rules: branch: release-1.25 dir: staging/src/k8s.io/pod-security-admission library: true +- destination: dynamic-resource-allocation + branches: + - name: master + dependencies: + - repository: apimachinery + branch: master + - repository: api + branch: master + - repository: client-go + branch: master + - repository: component-base + branch: master + - repository: kubelet + branch: master + source: + branch: master + dir: staging/src/k8s.io/dynamic-resource-allocation recursive-delete-patterns: - '*/.gitattributes' default-go-version: 1.19.3 diff --git a/staging/src/k8s.io/api/core/v1/generated.pb.go b/staging/src/k8s.io/api/core/v1/generated.pb.go index 4c0456cb616..a8df2b222e9 100644 --- a/staging/src/k8s.io/api/core/v1/generated.pb.go +++ b/staging/src/k8s.io/api/core/v1/generated.pb.go @@ -469,10 +469,38 @@ func (m *CinderVolumeSource) XXX_DiscardUnknown() { var xxx_messageInfo_CinderVolumeSource proto.InternalMessageInfo +func (m *ClaimSource) Reset() { *m = ClaimSource{} } +func (*ClaimSource) ProtoMessage() {} +func (*ClaimSource) Descriptor() ([]byte, []int) { + return fileDescriptor_83c10c24ec417dc9, []int{15} +} +func (m *ClaimSource) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ClaimSource) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ClaimSource) XXX_Merge(src proto.Message) { + xxx_messageInfo_ClaimSource.Merge(m, src) +} +func (m *ClaimSource) XXX_Size() int { + return m.Size() +} +func (m *ClaimSource) XXX_DiscardUnknown() { + xxx_messageInfo_ClaimSource.DiscardUnknown(m) +} + +var xxx_messageInfo_ClaimSource proto.InternalMessageInfo + func (m *ClientIPConfig) Reset() { *m = ClientIPConfig{} } func (*ClientIPConfig) ProtoMessage() {} func (*ClientIPConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{15} + return fileDescriptor_83c10c24ec417dc9, []int{16} } func (m *ClientIPConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -500,7 +528,7 @@ var xxx_messageInfo_ClientIPConfig proto.InternalMessageInfo func (m *ComponentCondition) Reset() { *m = ComponentCondition{} } func (*ComponentCondition) ProtoMessage() {} func (*ComponentCondition) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{16} + return fileDescriptor_83c10c24ec417dc9, []int{17} } func (m *ComponentCondition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -528,7 +556,7 @@ var xxx_messageInfo_ComponentCondition proto.InternalMessageInfo func (m *ComponentStatus) Reset() { *m = ComponentStatus{} } func (*ComponentStatus) ProtoMessage() {} func (*ComponentStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{17} + return fileDescriptor_83c10c24ec417dc9, []int{18} } func (m *ComponentStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -556,7 +584,7 @@ var xxx_messageInfo_ComponentStatus proto.InternalMessageInfo func (m *ComponentStatusList) Reset() { *m = ComponentStatusList{} } func (*ComponentStatusList) ProtoMessage() {} func (*ComponentStatusList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{18} + return fileDescriptor_83c10c24ec417dc9, []int{19} } func (m *ComponentStatusList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -584,7 +612,7 @@ var xxx_messageInfo_ComponentStatusList proto.InternalMessageInfo func (m *ConfigMap) Reset() { *m = ConfigMap{} } func (*ConfigMap) ProtoMessage() {} func (*ConfigMap) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{19} + return fileDescriptor_83c10c24ec417dc9, []int{20} } func (m *ConfigMap) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -612,7 +640,7 @@ var xxx_messageInfo_ConfigMap proto.InternalMessageInfo func (m *ConfigMapEnvSource) Reset() { *m = ConfigMapEnvSource{} } func (*ConfigMapEnvSource) ProtoMessage() {} func (*ConfigMapEnvSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{20} + return fileDescriptor_83c10c24ec417dc9, []int{21} } func (m *ConfigMapEnvSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -640,7 +668,7 @@ var xxx_messageInfo_ConfigMapEnvSource proto.InternalMessageInfo func (m *ConfigMapKeySelector) Reset() { *m = ConfigMapKeySelector{} } func (*ConfigMapKeySelector) ProtoMessage() {} func (*ConfigMapKeySelector) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{21} + return fileDescriptor_83c10c24ec417dc9, []int{22} } func (m *ConfigMapKeySelector) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -668,7 +696,7 @@ var xxx_messageInfo_ConfigMapKeySelector proto.InternalMessageInfo func (m *ConfigMapList) Reset() { *m = ConfigMapList{} } func (*ConfigMapList) ProtoMessage() {} func (*ConfigMapList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{22} + return fileDescriptor_83c10c24ec417dc9, []int{23} } func (m *ConfigMapList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -696,7 +724,7 @@ var xxx_messageInfo_ConfigMapList proto.InternalMessageInfo func (m *ConfigMapNodeConfigSource) Reset() { *m = ConfigMapNodeConfigSource{} } func (*ConfigMapNodeConfigSource) ProtoMessage() {} func (*ConfigMapNodeConfigSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{23} + return fileDescriptor_83c10c24ec417dc9, []int{24} } func (m *ConfigMapNodeConfigSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -724,7 +752,7 @@ var xxx_messageInfo_ConfigMapNodeConfigSource proto.InternalMessageInfo func (m *ConfigMapProjection) Reset() { *m = ConfigMapProjection{} } func (*ConfigMapProjection) ProtoMessage() {} func (*ConfigMapProjection) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{24} + return fileDescriptor_83c10c24ec417dc9, []int{25} } func (m *ConfigMapProjection) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -752,7 +780,7 @@ var xxx_messageInfo_ConfigMapProjection proto.InternalMessageInfo func (m *ConfigMapVolumeSource) Reset() { *m = ConfigMapVolumeSource{} } func (*ConfigMapVolumeSource) ProtoMessage() {} func (*ConfigMapVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{25} + return fileDescriptor_83c10c24ec417dc9, []int{26} } func (m *ConfigMapVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -780,7 +808,7 @@ var xxx_messageInfo_ConfigMapVolumeSource proto.InternalMessageInfo func (m *Container) Reset() { *m = Container{} } func (*Container) ProtoMessage() {} func (*Container) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{26} + return fileDescriptor_83c10c24ec417dc9, []int{27} } func (m *Container) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -808,7 +836,7 @@ var xxx_messageInfo_Container proto.InternalMessageInfo func (m *ContainerImage) Reset() { *m = ContainerImage{} } func (*ContainerImage) ProtoMessage() {} func (*ContainerImage) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{27} + return fileDescriptor_83c10c24ec417dc9, []int{28} } func (m *ContainerImage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -836,7 +864,7 @@ var xxx_messageInfo_ContainerImage proto.InternalMessageInfo func (m *ContainerPort) Reset() { *m = ContainerPort{} } func (*ContainerPort) ProtoMessage() {} func (*ContainerPort) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{28} + return fileDescriptor_83c10c24ec417dc9, []int{29} } func (m *ContainerPort) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -864,7 +892,7 @@ var xxx_messageInfo_ContainerPort proto.InternalMessageInfo func (m *ContainerState) Reset() { *m = ContainerState{} } func (*ContainerState) ProtoMessage() {} func (*ContainerState) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{29} + return fileDescriptor_83c10c24ec417dc9, []int{30} } func (m *ContainerState) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -892,7 +920,7 @@ var xxx_messageInfo_ContainerState proto.InternalMessageInfo func (m *ContainerStateRunning) Reset() { *m = ContainerStateRunning{} } func (*ContainerStateRunning) ProtoMessage() {} func (*ContainerStateRunning) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{30} + return fileDescriptor_83c10c24ec417dc9, []int{31} } func (m *ContainerStateRunning) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -920,7 +948,7 @@ var xxx_messageInfo_ContainerStateRunning proto.InternalMessageInfo func (m *ContainerStateTerminated) Reset() { *m = ContainerStateTerminated{} } func (*ContainerStateTerminated) ProtoMessage() {} func (*ContainerStateTerminated) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{31} + return fileDescriptor_83c10c24ec417dc9, []int{32} } func (m *ContainerStateTerminated) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -948,7 +976,7 @@ var xxx_messageInfo_ContainerStateTerminated proto.InternalMessageInfo func (m *ContainerStateWaiting) Reset() { *m = ContainerStateWaiting{} } func (*ContainerStateWaiting) ProtoMessage() {} func (*ContainerStateWaiting) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{32} + return fileDescriptor_83c10c24ec417dc9, []int{33} } func (m *ContainerStateWaiting) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -976,7 +1004,7 @@ var xxx_messageInfo_ContainerStateWaiting proto.InternalMessageInfo func (m *ContainerStatus) Reset() { *m = ContainerStatus{} } func (*ContainerStatus) ProtoMessage() {} func (*ContainerStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{33} + return fileDescriptor_83c10c24ec417dc9, []int{34} } func (m *ContainerStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1004,7 +1032,7 @@ var xxx_messageInfo_ContainerStatus proto.InternalMessageInfo func (m *DaemonEndpoint) Reset() { *m = DaemonEndpoint{} } func (*DaemonEndpoint) ProtoMessage() {} func (*DaemonEndpoint) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{34} + return fileDescriptor_83c10c24ec417dc9, []int{35} } func (m *DaemonEndpoint) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1032,7 +1060,7 @@ var xxx_messageInfo_DaemonEndpoint proto.InternalMessageInfo func (m *DownwardAPIProjection) Reset() { *m = DownwardAPIProjection{} } func (*DownwardAPIProjection) ProtoMessage() {} func (*DownwardAPIProjection) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{35} + return fileDescriptor_83c10c24ec417dc9, []int{36} } func (m *DownwardAPIProjection) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1060,7 +1088,7 @@ var xxx_messageInfo_DownwardAPIProjection proto.InternalMessageInfo func (m *DownwardAPIVolumeFile) Reset() { *m = DownwardAPIVolumeFile{} } func (*DownwardAPIVolumeFile) ProtoMessage() {} func (*DownwardAPIVolumeFile) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{36} + return fileDescriptor_83c10c24ec417dc9, []int{37} } func (m *DownwardAPIVolumeFile) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1088,7 +1116,7 @@ var xxx_messageInfo_DownwardAPIVolumeFile proto.InternalMessageInfo func (m *DownwardAPIVolumeSource) Reset() { *m = DownwardAPIVolumeSource{} } func (*DownwardAPIVolumeSource) ProtoMessage() {} func (*DownwardAPIVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{37} + return fileDescriptor_83c10c24ec417dc9, []int{38} } func (m *DownwardAPIVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1116,7 +1144,7 @@ var xxx_messageInfo_DownwardAPIVolumeSource proto.InternalMessageInfo func (m *EmptyDirVolumeSource) Reset() { *m = EmptyDirVolumeSource{} } func (*EmptyDirVolumeSource) ProtoMessage() {} func (*EmptyDirVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{38} + return fileDescriptor_83c10c24ec417dc9, []int{39} } func (m *EmptyDirVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1144,7 +1172,7 @@ var xxx_messageInfo_EmptyDirVolumeSource proto.InternalMessageInfo func (m *EndpointAddress) Reset() { *m = EndpointAddress{} } func (*EndpointAddress) ProtoMessage() {} func (*EndpointAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{39} + return fileDescriptor_83c10c24ec417dc9, []int{40} } func (m *EndpointAddress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1172,7 +1200,7 @@ var xxx_messageInfo_EndpointAddress proto.InternalMessageInfo func (m *EndpointPort) Reset() { *m = EndpointPort{} } func (*EndpointPort) ProtoMessage() {} func (*EndpointPort) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{40} + return fileDescriptor_83c10c24ec417dc9, []int{41} } func (m *EndpointPort) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1200,7 +1228,7 @@ var xxx_messageInfo_EndpointPort proto.InternalMessageInfo func (m *EndpointSubset) Reset() { *m = EndpointSubset{} } func (*EndpointSubset) ProtoMessage() {} func (*EndpointSubset) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{41} + return fileDescriptor_83c10c24ec417dc9, []int{42} } func (m *EndpointSubset) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1228,7 +1256,7 @@ var xxx_messageInfo_EndpointSubset proto.InternalMessageInfo func (m *Endpoints) Reset() { *m = Endpoints{} } func (*Endpoints) ProtoMessage() {} func (*Endpoints) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{42} + return fileDescriptor_83c10c24ec417dc9, []int{43} } func (m *Endpoints) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1256,7 +1284,7 @@ var xxx_messageInfo_Endpoints proto.InternalMessageInfo func (m *EndpointsList) Reset() { *m = EndpointsList{} } func (*EndpointsList) ProtoMessage() {} func (*EndpointsList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{43} + return fileDescriptor_83c10c24ec417dc9, []int{44} } func (m *EndpointsList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1284,7 +1312,7 @@ var xxx_messageInfo_EndpointsList proto.InternalMessageInfo func (m *EnvFromSource) Reset() { *m = EnvFromSource{} } func (*EnvFromSource) ProtoMessage() {} func (*EnvFromSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{44} + return fileDescriptor_83c10c24ec417dc9, []int{45} } func (m *EnvFromSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1312,7 +1340,7 @@ var xxx_messageInfo_EnvFromSource proto.InternalMessageInfo func (m *EnvVar) Reset() { *m = EnvVar{} } func (*EnvVar) ProtoMessage() {} func (*EnvVar) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{45} + return fileDescriptor_83c10c24ec417dc9, []int{46} } func (m *EnvVar) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1340,7 +1368,7 @@ var xxx_messageInfo_EnvVar proto.InternalMessageInfo func (m *EnvVarSource) Reset() { *m = EnvVarSource{} } func (*EnvVarSource) ProtoMessage() {} func (*EnvVarSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{46} + return fileDescriptor_83c10c24ec417dc9, []int{47} } func (m *EnvVarSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1368,7 +1396,7 @@ var xxx_messageInfo_EnvVarSource proto.InternalMessageInfo func (m *EphemeralContainer) Reset() { *m = EphemeralContainer{} } func (*EphemeralContainer) ProtoMessage() {} func (*EphemeralContainer) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{47} + return fileDescriptor_83c10c24ec417dc9, []int{48} } func (m *EphemeralContainer) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1396,7 +1424,7 @@ var xxx_messageInfo_EphemeralContainer proto.InternalMessageInfo func (m *EphemeralContainerCommon) Reset() { *m = EphemeralContainerCommon{} } func (*EphemeralContainerCommon) ProtoMessage() {} func (*EphemeralContainerCommon) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{48} + return fileDescriptor_83c10c24ec417dc9, []int{49} } func (m *EphemeralContainerCommon) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1424,7 +1452,7 @@ var xxx_messageInfo_EphemeralContainerCommon proto.InternalMessageInfo func (m *EphemeralVolumeSource) Reset() { *m = EphemeralVolumeSource{} } func (*EphemeralVolumeSource) ProtoMessage() {} func (*EphemeralVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{49} + return fileDescriptor_83c10c24ec417dc9, []int{50} } func (m *EphemeralVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1452,7 +1480,7 @@ var xxx_messageInfo_EphemeralVolumeSource proto.InternalMessageInfo func (m *Event) Reset() { *m = Event{} } func (*Event) ProtoMessage() {} func (*Event) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{50} + return fileDescriptor_83c10c24ec417dc9, []int{51} } func (m *Event) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1480,7 +1508,7 @@ var xxx_messageInfo_Event proto.InternalMessageInfo func (m *EventList) Reset() { *m = EventList{} } func (*EventList) ProtoMessage() {} func (*EventList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{51} + return fileDescriptor_83c10c24ec417dc9, []int{52} } func (m *EventList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1508,7 +1536,7 @@ var xxx_messageInfo_EventList proto.InternalMessageInfo func (m *EventSeries) Reset() { *m = EventSeries{} } func (*EventSeries) ProtoMessage() {} func (*EventSeries) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{52} + return fileDescriptor_83c10c24ec417dc9, []int{53} } func (m *EventSeries) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1536,7 +1564,7 @@ var xxx_messageInfo_EventSeries proto.InternalMessageInfo func (m *EventSource) Reset() { *m = EventSource{} } func (*EventSource) ProtoMessage() {} func (*EventSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{53} + return fileDescriptor_83c10c24ec417dc9, []int{54} } func (m *EventSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1564,7 +1592,7 @@ var xxx_messageInfo_EventSource proto.InternalMessageInfo func (m *ExecAction) Reset() { *m = ExecAction{} } func (*ExecAction) ProtoMessage() {} func (*ExecAction) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{54} + return fileDescriptor_83c10c24ec417dc9, []int{55} } func (m *ExecAction) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1592,7 +1620,7 @@ var xxx_messageInfo_ExecAction proto.InternalMessageInfo func (m *FCVolumeSource) Reset() { *m = FCVolumeSource{} } func (*FCVolumeSource) ProtoMessage() {} func (*FCVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{55} + return fileDescriptor_83c10c24ec417dc9, []int{56} } func (m *FCVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1620,7 +1648,7 @@ var xxx_messageInfo_FCVolumeSource proto.InternalMessageInfo func (m *FlexPersistentVolumeSource) Reset() { *m = FlexPersistentVolumeSource{} } func (*FlexPersistentVolumeSource) ProtoMessage() {} func (*FlexPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{56} + return fileDescriptor_83c10c24ec417dc9, []int{57} } func (m *FlexPersistentVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1648,7 +1676,7 @@ var xxx_messageInfo_FlexPersistentVolumeSource proto.InternalMessageInfo func (m *FlexVolumeSource) Reset() { *m = FlexVolumeSource{} } func (*FlexVolumeSource) ProtoMessage() {} func (*FlexVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{57} + return fileDescriptor_83c10c24ec417dc9, []int{58} } func (m *FlexVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1676,7 +1704,7 @@ var xxx_messageInfo_FlexVolumeSource proto.InternalMessageInfo func (m *FlockerVolumeSource) Reset() { *m = FlockerVolumeSource{} } func (*FlockerVolumeSource) ProtoMessage() {} func (*FlockerVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{58} + return fileDescriptor_83c10c24ec417dc9, []int{59} } func (m *FlockerVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1704,7 +1732,7 @@ var xxx_messageInfo_FlockerVolumeSource proto.InternalMessageInfo func (m *GCEPersistentDiskVolumeSource) Reset() { *m = GCEPersistentDiskVolumeSource{} } func (*GCEPersistentDiskVolumeSource) ProtoMessage() {} func (*GCEPersistentDiskVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{59} + return fileDescriptor_83c10c24ec417dc9, []int{60} } func (m *GCEPersistentDiskVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1732,7 +1760,7 @@ var xxx_messageInfo_GCEPersistentDiskVolumeSource proto.InternalMessageInfo func (m *GRPCAction) Reset() { *m = GRPCAction{} } func (*GRPCAction) ProtoMessage() {} func (*GRPCAction) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{60} + return fileDescriptor_83c10c24ec417dc9, []int{61} } func (m *GRPCAction) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1760,7 +1788,7 @@ var xxx_messageInfo_GRPCAction proto.InternalMessageInfo func (m *GitRepoVolumeSource) Reset() { *m = GitRepoVolumeSource{} } func (*GitRepoVolumeSource) ProtoMessage() {} func (*GitRepoVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{61} + return fileDescriptor_83c10c24ec417dc9, []int{62} } func (m *GitRepoVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1788,7 +1816,7 @@ var xxx_messageInfo_GitRepoVolumeSource proto.InternalMessageInfo func (m *GlusterfsPersistentVolumeSource) Reset() { *m = GlusterfsPersistentVolumeSource{} } func (*GlusterfsPersistentVolumeSource) ProtoMessage() {} func (*GlusterfsPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{62} + return fileDescriptor_83c10c24ec417dc9, []int{63} } func (m *GlusterfsPersistentVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1816,7 +1844,7 @@ var xxx_messageInfo_GlusterfsPersistentVolumeSource proto.InternalMessageInfo func (m *GlusterfsVolumeSource) Reset() { *m = GlusterfsVolumeSource{} } func (*GlusterfsVolumeSource) ProtoMessage() {} func (*GlusterfsVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{63} + return fileDescriptor_83c10c24ec417dc9, []int{64} } func (m *GlusterfsVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1844,7 +1872,7 @@ var xxx_messageInfo_GlusterfsVolumeSource proto.InternalMessageInfo func (m *HTTPGetAction) Reset() { *m = HTTPGetAction{} } func (*HTTPGetAction) ProtoMessage() {} func (*HTTPGetAction) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{64} + return fileDescriptor_83c10c24ec417dc9, []int{65} } func (m *HTTPGetAction) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1872,7 +1900,7 @@ var xxx_messageInfo_HTTPGetAction proto.InternalMessageInfo func (m *HTTPHeader) Reset() { *m = HTTPHeader{} } func (*HTTPHeader) ProtoMessage() {} func (*HTTPHeader) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{65} + return fileDescriptor_83c10c24ec417dc9, []int{66} } func (m *HTTPHeader) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1900,7 +1928,7 @@ var xxx_messageInfo_HTTPHeader proto.InternalMessageInfo func (m *HostAlias) Reset() { *m = HostAlias{} } func (*HostAlias) ProtoMessage() {} func (*HostAlias) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{66} + return fileDescriptor_83c10c24ec417dc9, []int{67} } func (m *HostAlias) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1928,7 +1956,7 @@ var xxx_messageInfo_HostAlias proto.InternalMessageInfo func (m *HostPathVolumeSource) Reset() { *m = HostPathVolumeSource{} } func (*HostPathVolumeSource) ProtoMessage() {} func (*HostPathVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{67} + return fileDescriptor_83c10c24ec417dc9, []int{68} } func (m *HostPathVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1956,7 +1984,7 @@ var xxx_messageInfo_HostPathVolumeSource proto.InternalMessageInfo func (m *ISCSIPersistentVolumeSource) Reset() { *m = ISCSIPersistentVolumeSource{} } func (*ISCSIPersistentVolumeSource) ProtoMessage() {} func (*ISCSIPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{68} + return fileDescriptor_83c10c24ec417dc9, []int{69} } func (m *ISCSIPersistentVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1984,7 +2012,7 @@ var xxx_messageInfo_ISCSIPersistentVolumeSource proto.InternalMessageInfo func (m *ISCSIVolumeSource) Reset() { *m = ISCSIVolumeSource{} } func (*ISCSIVolumeSource) ProtoMessage() {} func (*ISCSIVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{69} + return fileDescriptor_83c10c24ec417dc9, []int{70} } func (m *ISCSIVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2012,7 +2040,7 @@ var xxx_messageInfo_ISCSIVolumeSource proto.InternalMessageInfo func (m *KeyToPath) Reset() { *m = KeyToPath{} } func (*KeyToPath) ProtoMessage() {} func (*KeyToPath) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{70} + return fileDescriptor_83c10c24ec417dc9, []int{71} } func (m *KeyToPath) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2040,7 +2068,7 @@ var xxx_messageInfo_KeyToPath proto.InternalMessageInfo func (m *Lifecycle) Reset() { *m = Lifecycle{} } func (*Lifecycle) ProtoMessage() {} func (*Lifecycle) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{71} + return fileDescriptor_83c10c24ec417dc9, []int{72} } func (m *Lifecycle) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2068,7 +2096,7 @@ var xxx_messageInfo_Lifecycle proto.InternalMessageInfo func (m *LifecycleHandler) Reset() { *m = LifecycleHandler{} } func (*LifecycleHandler) ProtoMessage() {} func (*LifecycleHandler) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{72} + return fileDescriptor_83c10c24ec417dc9, []int{73} } func (m *LifecycleHandler) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2096,7 +2124,7 @@ var xxx_messageInfo_LifecycleHandler proto.InternalMessageInfo func (m *LimitRange) Reset() { *m = LimitRange{} } func (*LimitRange) ProtoMessage() {} func (*LimitRange) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{73} + return fileDescriptor_83c10c24ec417dc9, []int{74} } func (m *LimitRange) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2124,7 +2152,7 @@ var xxx_messageInfo_LimitRange proto.InternalMessageInfo func (m *LimitRangeItem) Reset() { *m = LimitRangeItem{} } func (*LimitRangeItem) ProtoMessage() {} func (*LimitRangeItem) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{74} + return fileDescriptor_83c10c24ec417dc9, []int{75} } func (m *LimitRangeItem) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2152,7 +2180,7 @@ var xxx_messageInfo_LimitRangeItem proto.InternalMessageInfo func (m *LimitRangeList) Reset() { *m = LimitRangeList{} } func (*LimitRangeList) ProtoMessage() {} func (*LimitRangeList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{75} + return fileDescriptor_83c10c24ec417dc9, []int{76} } func (m *LimitRangeList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2180,7 +2208,7 @@ var xxx_messageInfo_LimitRangeList proto.InternalMessageInfo func (m *LimitRangeSpec) Reset() { *m = LimitRangeSpec{} } func (*LimitRangeSpec) ProtoMessage() {} func (*LimitRangeSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{76} + return fileDescriptor_83c10c24ec417dc9, []int{77} } func (m *LimitRangeSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2208,7 +2236,7 @@ var xxx_messageInfo_LimitRangeSpec proto.InternalMessageInfo func (m *List) Reset() { *m = List{} } func (*List) ProtoMessage() {} func (*List) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{77} + return fileDescriptor_83c10c24ec417dc9, []int{78} } func (m *List) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2236,7 +2264,7 @@ var xxx_messageInfo_List proto.InternalMessageInfo func (m *LoadBalancerIngress) Reset() { *m = LoadBalancerIngress{} } func (*LoadBalancerIngress) ProtoMessage() {} func (*LoadBalancerIngress) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{78} + return fileDescriptor_83c10c24ec417dc9, []int{79} } func (m *LoadBalancerIngress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2264,7 +2292,7 @@ var xxx_messageInfo_LoadBalancerIngress proto.InternalMessageInfo func (m *LoadBalancerStatus) Reset() { *m = LoadBalancerStatus{} } func (*LoadBalancerStatus) ProtoMessage() {} func (*LoadBalancerStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{79} + return fileDescriptor_83c10c24ec417dc9, []int{80} } func (m *LoadBalancerStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2292,7 +2320,7 @@ var xxx_messageInfo_LoadBalancerStatus proto.InternalMessageInfo func (m *LocalObjectReference) Reset() { *m = LocalObjectReference{} } func (*LocalObjectReference) ProtoMessage() {} func (*LocalObjectReference) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{80} + return fileDescriptor_83c10c24ec417dc9, []int{81} } func (m *LocalObjectReference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2320,7 +2348,7 @@ var xxx_messageInfo_LocalObjectReference proto.InternalMessageInfo func (m *LocalVolumeSource) Reset() { *m = LocalVolumeSource{} } func (*LocalVolumeSource) ProtoMessage() {} func (*LocalVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{81} + return fileDescriptor_83c10c24ec417dc9, []int{82} } func (m *LocalVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2348,7 +2376,7 @@ var xxx_messageInfo_LocalVolumeSource proto.InternalMessageInfo func (m *NFSVolumeSource) Reset() { *m = NFSVolumeSource{} } func (*NFSVolumeSource) ProtoMessage() {} func (*NFSVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{82} + return fileDescriptor_83c10c24ec417dc9, []int{83} } func (m *NFSVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2376,7 +2404,7 @@ var xxx_messageInfo_NFSVolumeSource proto.InternalMessageInfo func (m *Namespace) Reset() { *m = Namespace{} } func (*Namespace) ProtoMessage() {} func (*Namespace) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{83} + return fileDescriptor_83c10c24ec417dc9, []int{84} } func (m *Namespace) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2404,7 +2432,7 @@ var xxx_messageInfo_Namespace proto.InternalMessageInfo func (m *NamespaceCondition) Reset() { *m = NamespaceCondition{} } func (*NamespaceCondition) ProtoMessage() {} func (*NamespaceCondition) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{84} + return fileDescriptor_83c10c24ec417dc9, []int{85} } func (m *NamespaceCondition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2432,7 +2460,7 @@ var xxx_messageInfo_NamespaceCondition proto.InternalMessageInfo func (m *NamespaceList) Reset() { *m = NamespaceList{} } func (*NamespaceList) ProtoMessage() {} func (*NamespaceList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{85} + return fileDescriptor_83c10c24ec417dc9, []int{86} } func (m *NamespaceList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2460,7 +2488,7 @@ var xxx_messageInfo_NamespaceList proto.InternalMessageInfo func (m *NamespaceSpec) Reset() { *m = NamespaceSpec{} } func (*NamespaceSpec) ProtoMessage() {} func (*NamespaceSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{86} + return fileDescriptor_83c10c24ec417dc9, []int{87} } func (m *NamespaceSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2488,7 +2516,7 @@ var xxx_messageInfo_NamespaceSpec proto.InternalMessageInfo func (m *NamespaceStatus) Reset() { *m = NamespaceStatus{} } func (*NamespaceStatus) ProtoMessage() {} func (*NamespaceStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{87} + return fileDescriptor_83c10c24ec417dc9, []int{88} } func (m *NamespaceStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2516,7 +2544,7 @@ var xxx_messageInfo_NamespaceStatus proto.InternalMessageInfo func (m *Node) Reset() { *m = Node{} } func (*Node) ProtoMessage() {} func (*Node) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{88} + return fileDescriptor_83c10c24ec417dc9, []int{89} } func (m *Node) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2544,7 +2572,7 @@ var xxx_messageInfo_Node proto.InternalMessageInfo func (m *NodeAddress) Reset() { *m = NodeAddress{} } func (*NodeAddress) ProtoMessage() {} func (*NodeAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{89} + return fileDescriptor_83c10c24ec417dc9, []int{90} } func (m *NodeAddress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2572,7 +2600,7 @@ var xxx_messageInfo_NodeAddress proto.InternalMessageInfo func (m *NodeAffinity) Reset() { *m = NodeAffinity{} } func (*NodeAffinity) ProtoMessage() {} func (*NodeAffinity) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{90} + return fileDescriptor_83c10c24ec417dc9, []int{91} } func (m *NodeAffinity) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2600,7 +2628,7 @@ var xxx_messageInfo_NodeAffinity proto.InternalMessageInfo func (m *NodeCondition) Reset() { *m = NodeCondition{} } func (*NodeCondition) ProtoMessage() {} func (*NodeCondition) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{91} + return fileDescriptor_83c10c24ec417dc9, []int{92} } func (m *NodeCondition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2628,7 +2656,7 @@ var xxx_messageInfo_NodeCondition proto.InternalMessageInfo func (m *NodeConfigSource) Reset() { *m = NodeConfigSource{} } func (*NodeConfigSource) ProtoMessage() {} func (*NodeConfigSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{92} + return fileDescriptor_83c10c24ec417dc9, []int{93} } func (m *NodeConfigSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2656,7 +2684,7 @@ var xxx_messageInfo_NodeConfigSource proto.InternalMessageInfo func (m *NodeConfigStatus) Reset() { *m = NodeConfigStatus{} } func (*NodeConfigStatus) ProtoMessage() {} func (*NodeConfigStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{93} + return fileDescriptor_83c10c24ec417dc9, []int{94} } func (m *NodeConfigStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2684,7 +2712,7 @@ var xxx_messageInfo_NodeConfigStatus proto.InternalMessageInfo func (m *NodeDaemonEndpoints) Reset() { *m = NodeDaemonEndpoints{} } func (*NodeDaemonEndpoints) ProtoMessage() {} func (*NodeDaemonEndpoints) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{94} + return fileDescriptor_83c10c24ec417dc9, []int{95} } func (m *NodeDaemonEndpoints) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2712,7 +2740,7 @@ var xxx_messageInfo_NodeDaemonEndpoints proto.InternalMessageInfo func (m *NodeList) Reset() { *m = NodeList{} } func (*NodeList) ProtoMessage() {} func (*NodeList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{95} + return fileDescriptor_83c10c24ec417dc9, []int{96} } func (m *NodeList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2740,7 +2768,7 @@ var xxx_messageInfo_NodeList proto.InternalMessageInfo func (m *NodeProxyOptions) Reset() { *m = NodeProxyOptions{} } func (*NodeProxyOptions) ProtoMessage() {} func (*NodeProxyOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{96} + return fileDescriptor_83c10c24ec417dc9, []int{97} } func (m *NodeProxyOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2768,7 +2796,7 @@ var xxx_messageInfo_NodeProxyOptions proto.InternalMessageInfo func (m *NodeResources) Reset() { *m = NodeResources{} } func (*NodeResources) ProtoMessage() {} func (*NodeResources) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{97} + return fileDescriptor_83c10c24ec417dc9, []int{98} } func (m *NodeResources) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2796,7 +2824,7 @@ var xxx_messageInfo_NodeResources proto.InternalMessageInfo func (m *NodeSelector) Reset() { *m = NodeSelector{} } func (*NodeSelector) ProtoMessage() {} func (*NodeSelector) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{98} + return fileDescriptor_83c10c24ec417dc9, []int{99} } func (m *NodeSelector) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2824,7 +2852,7 @@ var xxx_messageInfo_NodeSelector proto.InternalMessageInfo func (m *NodeSelectorRequirement) Reset() { *m = NodeSelectorRequirement{} } func (*NodeSelectorRequirement) ProtoMessage() {} func (*NodeSelectorRequirement) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{99} + return fileDescriptor_83c10c24ec417dc9, []int{100} } func (m *NodeSelectorRequirement) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2852,7 +2880,7 @@ var xxx_messageInfo_NodeSelectorRequirement proto.InternalMessageInfo func (m *NodeSelectorTerm) Reset() { *m = NodeSelectorTerm{} } func (*NodeSelectorTerm) ProtoMessage() {} func (*NodeSelectorTerm) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{100} + return fileDescriptor_83c10c24ec417dc9, []int{101} } func (m *NodeSelectorTerm) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2880,7 +2908,7 @@ var xxx_messageInfo_NodeSelectorTerm proto.InternalMessageInfo func (m *NodeSpec) Reset() { *m = NodeSpec{} } func (*NodeSpec) ProtoMessage() {} func (*NodeSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{101} + return fileDescriptor_83c10c24ec417dc9, []int{102} } func (m *NodeSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2908,7 +2936,7 @@ var xxx_messageInfo_NodeSpec proto.InternalMessageInfo func (m *NodeStatus) Reset() { *m = NodeStatus{} } func (*NodeStatus) ProtoMessage() {} func (*NodeStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{102} + return fileDescriptor_83c10c24ec417dc9, []int{103} } func (m *NodeStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2936,7 +2964,7 @@ var xxx_messageInfo_NodeStatus proto.InternalMessageInfo func (m *NodeSystemInfo) Reset() { *m = NodeSystemInfo{} } func (*NodeSystemInfo) ProtoMessage() {} func (*NodeSystemInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{103} + return fileDescriptor_83c10c24ec417dc9, []int{104} } func (m *NodeSystemInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2964,7 +2992,7 @@ var xxx_messageInfo_NodeSystemInfo proto.InternalMessageInfo func (m *ObjectFieldSelector) Reset() { *m = ObjectFieldSelector{} } func (*ObjectFieldSelector) ProtoMessage() {} func (*ObjectFieldSelector) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{104} + return fileDescriptor_83c10c24ec417dc9, []int{105} } func (m *ObjectFieldSelector) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2992,7 +3020,7 @@ var xxx_messageInfo_ObjectFieldSelector proto.InternalMessageInfo func (m *ObjectReference) Reset() { *m = ObjectReference{} } func (*ObjectReference) ProtoMessage() {} func (*ObjectReference) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{105} + return fileDescriptor_83c10c24ec417dc9, []int{106} } func (m *ObjectReference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3020,7 +3048,7 @@ var xxx_messageInfo_ObjectReference proto.InternalMessageInfo func (m *PersistentVolume) Reset() { *m = PersistentVolume{} } func (*PersistentVolume) ProtoMessage() {} func (*PersistentVolume) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{106} + return fileDescriptor_83c10c24ec417dc9, []int{107} } func (m *PersistentVolume) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3048,7 +3076,7 @@ var xxx_messageInfo_PersistentVolume proto.InternalMessageInfo func (m *PersistentVolumeClaim) Reset() { *m = PersistentVolumeClaim{} } func (*PersistentVolumeClaim) ProtoMessage() {} func (*PersistentVolumeClaim) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{107} + return fileDescriptor_83c10c24ec417dc9, []int{108} } func (m *PersistentVolumeClaim) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3076,7 +3104,7 @@ var xxx_messageInfo_PersistentVolumeClaim proto.InternalMessageInfo func (m *PersistentVolumeClaimCondition) Reset() { *m = PersistentVolumeClaimCondition{} } func (*PersistentVolumeClaimCondition) ProtoMessage() {} func (*PersistentVolumeClaimCondition) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{108} + return fileDescriptor_83c10c24ec417dc9, []int{109} } func (m *PersistentVolumeClaimCondition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3104,7 +3132,7 @@ var xxx_messageInfo_PersistentVolumeClaimCondition proto.InternalMessageInfo func (m *PersistentVolumeClaimList) Reset() { *m = PersistentVolumeClaimList{} } func (*PersistentVolumeClaimList) ProtoMessage() {} func (*PersistentVolumeClaimList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{109} + return fileDescriptor_83c10c24ec417dc9, []int{110} } func (m *PersistentVolumeClaimList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3132,7 +3160,7 @@ var xxx_messageInfo_PersistentVolumeClaimList proto.InternalMessageInfo func (m *PersistentVolumeClaimSpec) Reset() { *m = PersistentVolumeClaimSpec{} } func (*PersistentVolumeClaimSpec) ProtoMessage() {} func (*PersistentVolumeClaimSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{110} + return fileDescriptor_83c10c24ec417dc9, []int{111} } func (m *PersistentVolumeClaimSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3160,7 +3188,7 @@ var xxx_messageInfo_PersistentVolumeClaimSpec proto.InternalMessageInfo func (m *PersistentVolumeClaimStatus) Reset() { *m = PersistentVolumeClaimStatus{} } func (*PersistentVolumeClaimStatus) ProtoMessage() {} func (*PersistentVolumeClaimStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{111} + return fileDescriptor_83c10c24ec417dc9, []int{112} } func (m *PersistentVolumeClaimStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3188,7 +3216,7 @@ var xxx_messageInfo_PersistentVolumeClaimStatus proto.InternalMessageInfo func (m *PersistentVolumeClaimTemplate) Reset() { *m = PersistentVolumeClaimTemplate{} } func (*PersistentVolumeClaimTemplate) ProtoMessage() {} func (*PersistentVolumeClaimTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{112} + return fileDescriptor_83c10c24ec417dc9, []int{113} } func (m *PersistentVolumeClaimTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3216,7 +3244,7 @@ var xxx_messageInfo_PersistentVolumeClaimTemplate proto.InternalMessageInfo func (m *PersistentVolumeClaimVolumeSource) Reset() { *m = PersistentVolumeClaimVolumeSource{} } func (*PersistentVolumeClaimVolumeSource) ProtoMessage() {} func (*PersistentVolumeClaimVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{113} + return fileDescriptor_83c10c24ec417dc9, []int{114} } func (m *PersistentVolumeClaimVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3244,7 +3272,7 @@ var xxx_messageInfo_PersistentVolumeClaimVolumeSource proto.InternalMessageInfo func (m *PersistentVolumeList) Reset() { *m = PersistentVolumeList{} } func (*PersistentVolumeList) ProtoMessage() {} func (*PersistentVolumeList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{114} + return fileDescriptor_83c10c24ec417dc9, []int{115} } func (m *PersistentVolumeList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3272,7 +3300,7 @@ var xxx_messageInfo_PersistentVolumeList proto.InternalMessageInfo func (m *PersistentVolumeSource) Reset() { *m = PersistentVolumeSource{} } func (*PersistentVolumeSource) ProtoMessage() {} func (*PersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{115} + return fileDescriptor_83c10c24ec417dc9, []int{116} } func (m *PersistentVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3300,7 +3328,7 @@ var xxx_messageInfo_PersistentVolumeSource proto.InternalMessageInfo func (m *PersistentVolumeSpec) Reset() { *m = PersistentVolumeSpec{} } func (*PersistentVolumeSpec) ProtoMessage() {} func (*PersistentVolumeSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{116} + return fileDescriptor_83c10c24ec417dc9, []int{117} } func (m *PersistentVolumeSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3328,7 +3356,7 @@ var xxx_messageInfo_PersistentVolumeSpec proto.InternalMessageInfo func (m *PersistentVolumeStatus) Reset() { *m = PersistentVolumeStatus{} } func (*PersistentVolumeStatus) ProtoMessage() {} func (*PersistentVolumeStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{117} + return fileDescriptor_83c10c24ec417dc9, []int{118} } func (m *PersistentVolumeStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3356,7 +3384,7 @@ var xxx_messageInfo_PersistentVolumeStatus proto.InternalMessageInfo func (m *PhotonPersistentDiskVolumeSource) Reset() { *m = PhotonPersistentDiskVolumeSource{} } func (*PhotonPersistentDiskVolumeSource) ProtoMessage() {} func (*PhotonPersistentDiskVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{118} + return fileDescriptor_83c10c24ec417dc9, []int{119} } func (m *PhotonPersistentDiskVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3384,7 +3412,7 @@ var xxx_messageInfo_PhotonPersistentDiskVolumeSource proto.InternalMessageInfo func (m *Pod) Reset() { *m = Pod{} } func (*Pod) ProtoMessage() {} func (*Pod) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{119} + return fileDescriptor_83c10c24ec417dc9, []int{120} } func (m *Pod) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3412,7 +3440,7 @@ var xxx_messageInfo_Pod proto.InternalMessageInfo func (m *PodAffinity) Reset() { *m = PodAffinity{} } func (*PodAffinity) ProtoMessage() {} func (*PodAffinity) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{120} + return fileDescriptor_83c10c24ec417dc9, []int{121} } func (m *PodAffinity) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3440,7 +3468,7 @@ var xxx_messageInfo_PodAffinity proto.InternalMessageInfo func (m *PodAffinityTerm) Reset() { *m = PodAffinityTerm{} } func (*PodAffinityTerm) ProtoMessage() {} func (*PodAffinityTerm) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{121} + return fileDescriptor_83c10c24ec417dc9, []int{122} } func (m *PodAffinityTerm) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3468,7 +3496,7 @@ var xxx_messageInfo_PodAffinityTerm proto.InternalMessageInfo func (m *PodAntiAffinity) Reset() { *m = PodAntiAffinity{} } func (*PodAntiAffinity) ProtoMessage() {} func (*PodAntiAffinity) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{122} + return fileDescriptor_83c10c24ec417dc9, []int{123} } func (m *PodAntiAffinity) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3496,7 +3524,7 @@ var xxx_messageInfo_PodAntiAffinity proto.InternalMessageInfo func (m *PodAttachOptions) Reset() { *m = PodAttachOptions{} } func (*PodAttachOptions) ProtoMessage() {} func (*PodAttachOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{123} + return fileDescriptor_83c10c24ec417dc9, []int{124} } func (m *PodAttachOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3524,7 +3552,7 @@ var xxx_messageInfo_PodAttachOptions proto.InternalMessageInfo func (m *PodCondition) Reset() { *m = PodCondition{} } func (*PodCondition) ProtoMessage() {} func (*PodCondition) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{124} + return fileDescriptor_83c10c24ec417dc9, []int{125} } func (m *PodCondition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3552,7 +3580,7 @@ var xxx_messageInfo_PodCondition proto.InternalMessageInfo func (m *PodDNSConfig) Reset() { *m = PodDNSConfig{} } func (*PodDNSConfig) ProtoMessage() {} func (*PodDNSConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{125} + return fileDescriptor_83c10c24ec417dc9, []int{126} } func (m *PodDNSConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3580,7 +3608,7 @@ var xxx_messageInfo_PodDNSConfig proto.InternalMessageInfo func (m *PodDNSConfigOption) Reset() { *m = PodDNSConfigOption{} } func (*PodDNSConfigOption) ProtoMessage() {} func (*PodDNSConfigOption) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{126} + return fileDescriptor_83c10c24ec417dc9, []int{127} } func (m *PodDNSConfigOption) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3608,7 +3636,7 @@ var xxx_messageInfo_PodDNSConfigOption proto.InternalMessageInfo func (m *PodExecOptions) Reset() { *m = PodExecOptions{} } func (*PodExecOptions) ProtoMessage() {} func (*PodExecOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{127} + return fileDescriptor_83c10c24ec417dc9, []int{128} } func (m *PodExecOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3636,7 +3664,7 @@ var xxx_messageInfo_PodExecOptions proto.InternalMessageInfo func (m *PodIP) Reset() { *m = PodIP{} } func (*PodIP) ProtoMessage() {} func (*PodIP) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{128} + return fileDescriptor_83c10c24ec417dc9, []int{129} } func (m *PodIP) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3664,7 +3692,7 @@ var xxx_messageInfo_PodIP proto.InternalMessageInfo func (m *PodList) Reset() { *m = PodList{} } func (*PodList) ProtoMessage() {} func (*PodList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{129} + return fileDescriptor_83c10c24ec417dc9, []int{130} } func (m *PodList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3692,7 +3720,7 @@ var xxx_messageInfo_PodList proto.InternalMessageInfo func (m *PodLogOptions) Reset() { *m = PodLogOptions{} } func (*PodLogOptions) ProtoMessage() {} func (*PodLogOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{130} + return fileDescriptor_83c10c24ec417dc9, []int{131} } func (m *PodLogOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3720,7 +3748,7 @@ var xxx_messageInfo_PodLogOptions proto.InternalMessageInfo func (m *PodOS) Reset() { *m = PodOS{} } func (*PodOS) ProtoMessage() {} func (*PodOS) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{131} + return fileDescriptor_83c10c24ec417dc9, []int{132} } func (m *PodOS) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3748,7 +3776,7 @@ var xxx_messageInfo_PodOS proto.InternalMessageInfo func (m *PodPortForwardOptions) Reset() { *m = PodPortForwardOptions{} } func (*PodPortForwardOptions) ProtoMessage() {} func (*PodPortForwardOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{132} + return fileDescriptor_83c10c24ec417dc9, []int{133} } func (m *PodPortForwardOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3776,7 +3804,7 @@ var xxx_messageInfo_PodPortForwardOptions proto.InternalMessageInfo func (m *PodProxyOptions) Reset() { *m = PodProxyOptions{} } func (*PodProxyOptions) ProtoMessage() {} func (*PodProxyOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{133} + return fileDescriptor_83c10c24ec417dc9, []int{134} } func (m *PodProxyOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3804,7 +3832,7 @@ var xxx_messageInfo_PodProxyOptions proto.InternalMessageInfo func (m *PodReadinessGate) Reset() { *m = PodReadinessGate{} } func (*PodReadinessGate) ProtoMessage() {} func (*PodReadinessGate) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{134} + return fileDescriptor_83c10c24ec417dc9, []int{135} } func (m *PodReadinessGate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3829,10 +3857,38 @@ func (m *PodReadinessGate) XXX_DiscardUnknown() { var xxx_messageInfo_PodReadinessGate proto.InternalMessageInfo +func (m *PodResourceClaim) Reset() { *m = PodResourceClaim{} } +func (*PodResourceClaim) ProtoMessage() {} +func (*PodResourceClaim) Descriptor() ([]byte, []int) { + return fileDescriptor_83c10c24ec417dc9, []int{136} +} +func (m *PodResourceClaim) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodResourceClaim) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *PodResourceClaim) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodResourceClaim.Merge(m, src) +} +func (m *PodResourceClaim) XXX_Size() int { + return m.Size() +} +func (m *PodResourceClaim) XXX_DiscardUnknown() { + xxx_messageInfo_PodResourceClaim.DiscardUnknown(m) +} + +var xxx_messageInfo_PodResourceClaim proto.InternalMessageInfo + func (m *PodSchedulingGate) Reset() { *m = PodSchedulingGate{} } func (*PodSchedulingGate) ProtoMessage() {} func (*PodSchedulingGate) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{135} + return fileDescriptor_83c10c24ec417dc9, []int{137} } func (m *PodSchedulingGate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3860,7 +3916,7 @@ var xxx_messageInfo_PodSchedulingGate proto.InternalMessageInfo func (m *PodSecurityContext) Reset() { *m = PodSecurityContext{} } func (*PodSecurityContext) ProtoMessage() {} func (*PodSecurityContext) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{136} + return fileDescriptor_83c10c24ec417dc9, []int{138} } func (m *PodSecurityContext) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3888,7 +3944,7 @@ var xxx_messageInfo_PodSecurityContext proto.InternalMessageInfo func (m *PodSignature) Reset() { *m = PodSignature{} } func (*PodSignature) ProtoMessage() {} func (*PodSignature) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{137} + return fileDescriptor_83c10c24ec417dc9, []int{139} } func (m *PodSignature) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3916,7 +3972,7 @@ var xxx_messageInfo_PodSignature proto.InternalMessageInfo func (m *PodSpec) Reset() { *m = PodSpec{} } func (*PodSpec) ProtoMessage() {} func (*PodSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{138} + return fileDescriptor_83c10c24ec417dc9, []int{140} } func (m *PodSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3944,7 +4000,7 @@ var xxx_messageInfo_PodSpec proto.InternalMessageInfo func (m *PodStatus) Reset() { *m = PodStatus{} } func (*PodStatus) ProtoMessage() {} func (*PodStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{139} + return fileDescriptor_83c10c24ec417dc9, []int{141} } func (m *PodStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3972,7 +4028,7 @@ var xxx_messageInfo_PodStatus proto.InternalMessageInfo func (m *PodStatusResult) Reset() { *m = PodStatusResult{} } func (*PodStatusResult) ProtoMessage() {} func (*PodStatusResult) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{140} + return fileDescriptor_83c10c24ec417dc9, []int{142} } func (m *PodStatusResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4000,7 +4056,7 @@ var xxx_messageInfo_PodStatusResult proto.InternalMessageInfo func (m *PodTemplate) Reset() { *m = PodTemplate{} } func (*PodTemplate) ProtoMessage() {} func (*PodTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{141} + return fileDescriptor_83c10c24ec417dc9, []int{143} } func (m *PodTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4028,7 +4084,7 @@ var xxx_messageInfo_PodTemplate proto.InternalMessageInfo func (m *PodTemplateList) Reset() { *m = PodTemplateList{} } func (*PodTemplateList) ProtoMessage() {} func (*PodTemplateList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{142} + return fileDescriptor_83c10c24ec417dc9, []int{144} } func (m *PodTemplateList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4056,7 +4112,7 @@ var xxx_messageInfo_PodTemplateList proto.InternalMessageInfo func (m *PodTemplateSpec) Reset() { *m = PodTemplateSpec{} } func (*PodTemplateSpec) ProtoMessage() {} func (*PodTemplateSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{143} + return fileDescriptor_83c10c24ec417dc9, []int{145} } func (m *PodTemplateSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4084,7 +4140,7 @@ var xxx_messageInfo_PodTemplateSpec proto.InternalMessageInfo func (m *PortStatus) Reset() { *m = PortStatus{} } func (*PortStatus) ProtoMessage() {} func (*PortStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{144} + return fileDescriptor_83c10c24ec417dc9, []int{146} } func (m *PortStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4112,7 +4168,7 @@ var xxx_messageInfo_PortStatus proto.InternalMessageInfo func (m *PortworxVolumeSource) Reset() { *m = PortworxVolumeSource{} } func (*PortworxVolumeSource) ProtoMessage() {} func (*PortworxVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{145} + return fileDescriptor_83c10c24ec417dc9, []int{147} } func (m *PortworxVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4140,7 +4196,7 @@ var xxx_messageInfo_PortworxVolumeSource proto.InternalMessageInfo func (m *Preconditions) Reset() { *m = Preconditions{} } func (*Preconditions) ProtoMessage() {} func (*Preconditions) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{146} + return fileDescriptor_83c10c24ec417dc9, []int{148} } func (m *Preconditions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4168,7 +4224,7 @@ var xxx_messageInfo_Preconditions proto.InternalMessageInfo func (m *PreferAvoidPodsEntry) Reset() { *m = PreferAvoidPodsEntry{} } func (*PreferAvoidPodsEntry) ProtoMessage() {} func (*PreferAvoidPodsEntry) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{147} + return fileDescriptor_83c10c24ec417dc9, []int{149} } func (m *PreferAvoidPodsEntry) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4196,7 +4252,7 @@ var xxx_messageInfo_PreferAvoidPodsEntry proto.InternalMessageInfo func (m *PreferredSchedulingTerm) Reset() { *m = PreferredSchedulingTerm{} } func (*PreferredSchedulingTerm) ProtoMessage() {} func (*PreferredSchedulingTerm) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{148} + return fileDescriptor_83c10c24ec417dc9, []int{150} } func (m *PreferredSchedulingTerm) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4224,7 +4280,7 @@ var xxx_messageInfo_PreferredSchedulingTerm proto.InternalMessageInfo func (m *Probe) Reset() { *m = Probe{} } func (*Probe) ProtoMessage() {} func (*Probe) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{149} + return fileDescriptor_83c10c24ec417dc9, []int{151} } func (m *Probe) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4252,7 +4308,7 @@ var xxx_messageInfo_Probe proto.InternalMessageInfo func (m *ProbeHandler) Reset() { *m = ProbeHandler{} } func (*ProbeHandler) ProtoMessage() {} func (*ProbeHandler) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{150} + return fileDescriptor_83c10c24ec417dc9, []int{152} } func (m *ProbeHandler) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4280,7 +4336,7 @@ var xxx_messageInfo_ProbeHandler proto.InternalMessageInfo func (m *ProjectedVolumeSource) Reset() { *m = ProjectedVolumeSource{} } func (*ProjectedVolumeSource) ProtoMessage() {} func (*ProjectedVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{151} + return fileDescriptor_83c10c24ec417dc9, []int{153} } func (m *ProjectedVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4308,7 +4364,7 @@ var xxx_messageInfo_ProjectedVolumeSource proto.InternalMessageInfo func (m *QuobyteVolumeSource) Reset() { *m = QuobyteVolumeSource{} } func (*QuobyteVolumeSource) ProtoMessage() {} func (*QuobyteVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{152} + return fileDescriptor_83c10c24ec417dc9, []int{154} } func (m *QuobyteVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4336,7 +4392,7 @@ var xxx_messageInfo_QuobyteVolumeSource proto.InternalMessageInfo func (m *RBDPersistentVolumeSource) Reset() { *m = RBDPersistentVolumeSource{} } func (*RBDPersistentVolumeSource) ProtoMessage() {} func (*RBDPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{153} + return fileDescriptor_83c10c24ec417dc9, []int{155} } func (m *RBDPersistentVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4364,7 +4420,7 @@ var xxx_messageInfo_RBDPersistentVolumeSource proto.InternalMessageInfo func (m *RBDVolumeSource) Reset() { *m = RBDVolumeSource{} } func (*RBDVolumeSource) ProtoMessage() {} func (*RBDVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{154} + return fileDescriptor_83c10c24ec417dc9, []int{156} } func (m *RBDVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4392,7 +4448,7 @@ var xxx_messageInfo_RBDVolumeSource proto.InternalMessageInfo func (m *RangeAllocation) Reset() { *m = RangeAllocation{} } func (*RangeAllocation) ProtoMessage() {} func (*RangeAllocation) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{155} + return fileDescriptor_83c10c24ec417dc9, []int{157} } func (m *RangeAllocation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4420,7 +4476,7 @@ var xxx_messageInfo_RangeAllocation proto.InternalMessageInfo func (m *ReplicationController) Reset() { *m = ReplicationController{} } func (*ReplicationController) ProtoMessage() {} func (*ReplicationController) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{156} + return fileDescriptor_83c10c24ec417dc9, []int{158} } func (m *ReplicationController) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4448,7 +4504,7 @@ var xxx_messageInfo_ReplicationController proto.InternalMessageInfo func (m *ReplicationControllerCondition) Reset() { *m = ReplicationControllerCondition{} } func (*ReplicationControllerCondition) ProtoMessage() {} func (*ReplicationControllerCondition) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{157} + return fileDescriptor_83c10c24ec417dc9, []int{159} } func (m *ReplicationControllerCondition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4476,7 +4532,7 @@ var xxx_messageInfo_ReplicationControllerCondition proto.InternalMessageInfo func (m *ReplicationControllerList) Reset() { *m = ReplicationControllerList{} } func (*ReplicationControllerList) ProtoMessage() {} func (*ReplicationControllerList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{158} + return fileDescriptor_83c10c24ec417dc9, []int{160} } func (m *ReplicationControllerList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4504,7 +4560,7 @@ var xxx_messageInfo_ReplicationControllerList proto.InternalMessageInfo func (m *ReplicationControllerSpec) Reset() { *m = ReplicationControllerSpec{} } func (*ReplicationControllerSpec) ProtoMessage() {} func (*ReplicationControllerSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{159} + return fileDescriptor_83c10c24ec417dc9, []int{161} } func (m *ReplicationControllerSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4532,7 +4588,7 @@ var xxx_messageInfo_ReplicationControllerSpec proto.InternalMessageInfo func (m *ReplicationControllerStatus) Reset() { *m = ReplicationControllerStatus{} } func (*ReplicationControllerStatus) ProtoMessage() {} func (*ReplicationControllerStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{160} + return fileDescriptor_83c10c24ec417dc9, []int{162} } func (m *ReplicationControllerStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4557,10 +4613,38 @@ func (m *ReplicationControllerStatus) XXX_DiscardUnknown() { var xxx_messageInfo_ReplicationControllerStatus proto.InternalMessageInfo +func (m *ResourceClaim) Reset() { *m = ResourceClaim{} } +func (*ResourceClaim) ProtoMessage() {} +func (*ResourceClaim) Descriptor() ([]byte, []int) { + return fileDescriptor_83c10c24ec417dc9, []int{163} +} +func (m *ResourceClaim) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClaim) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClaim) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClaim.Merge(m, src) +} +func (m *ResourceClaim) XXX_Size() int { + return m.Size() +} +func (m *ResourceClaim) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClaim.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClaim proto.InternalMessageInfo + func (m *ResourceFieldSelector) Reset() { *m = ResourceFieldSelector{} } func (*ResourceFieldSelector) ProtoMessage() {} func (*ResourceFieldSelector) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{161} + return fileDescriptor_83c10c24ec417dc9, []int{164} } func (m *ResourceFieldSelector) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4588,7 +4672,7 @@ var xxx_messageInfo_ResourceFieldSelector proto.InternalMessageInfo func (m *ResourceQuota) Reset() { *m = ResourceQuota{} } func (*ResourceQuota) ProtoMessage() {} func (*ResourceQuota) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{162} + return fileDescriptor_83c10c24ec417dc9, []int{165} } func (m *ResourceQuota) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4616,7 +4700,7 @@ var xxx_messageInfo_ResourceQuota proto.InternalMessageInfo func (m *ResourceQuotaList) Reset() { *m = ResourceQuotaList{} } func (*ResourceQuotaList) ProtoMessage() {} func (*ResourceQuotaList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{163} + return fileDescriptor_83c10c24ec417dc9, []int{166} } func (m *ResourceQuotaList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4644,7 +4728,7 @@ var xxx_messageInfo_ResourceQuotaList proto.InternalMessageInfo func (m *ResourceQuotaSpec) Reset() { *m = ResourceQuotaSpec{} } func (*ResourceQuotaSpec) ProtoMessage() {} func (*ResourceQuotaSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{164} + return fileDescriptor_83c10c24ec417dc9, []int{167} } func (m *ResourceQuotaSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4672,7 +4756,7 @@ var xxx_messageInfo_ResourceQuotaSpec proto.InternalMessageInfo func (m *ResourceQuotaStatus) Reset() { *m = ResourceQuotaStatus{} } func (*ResourceQuotaStatus) ProtoMessage() {} func (*ResourceQuotaStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{165} + return fileDescriptor_83c10c24ec417dc9, []int{168} } func (m *ResourceQuotaStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4700,7 +4784,7 @@ var xxx_messageInfo_ResourceQuotaStatus proto.InternalMessageInfo func (m *ResourceRequirements) Reset() { *m = ResourceRequirements{} } func (*ResourceRequirements) ProtoMessage() {} func (*ResourceRequirements) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{166} + return fileDescriptor_83c10c24ec417dc9, []int{169} } func (m *ResourceRequirements) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4728,7 +4812,7 @@ var xxx_messageInfo_ResourceRequirements proto.InternalMessageInfo func (m *SELinuxOptions) Reset() { *m = SELinuxOptions{} } func (*SELinuxOptions) ProtoMessage() {} func (*SELinuxOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{167} + return fileDescriptor_83c10c24ec417dc9, []int{170} } func (m *SELinuxOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4756,7 +4840,7 @@ var xxx_messageInfo_SELinuxOptions proto.InternalMessageInfo func (m *ScaleIOPersistentVolumeSource) Reset() { *m = ScaleIOPersistentVolumeSource{} } func (*ScaleIOPersistentVolumeSource) ProtoMessage() {} func (*ScaleIOPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{168} + return fileDescriptor_83c10c24ec417dc9, []int{171} } func (m *ScaleIOPersistentVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4784,7 +4868,7 @@ var xxx_messageInfo_ScaleIOPersistentVolumeSource proto.InternalMessageInfo func (m *ScaleIOVolumeSource) Reset() { *m = ScaleIOVolumeSource{} } func (*ScaleIOVolumeSource) ProtoMessage() {} func (*ScaleIOVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{169} + return fileDescriptor_83c10c24ec417dc9, []int{172} } func (m *ScaleIOVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4812,7 +4896,7 @@ var xxx_messageInfo_ScaleIOVolumeSource proto.InternalMessageInfo func (m *ScopeSelector) Reset() { *m = ScopeSelector{} } func (*ScopeSelector) ProtoMessage() {} func (*ScopeSelector) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{170} + return fileDescriptor_83c10c24ec417dc9, []int{173} } func (m *ScopeSelector) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4840,7 +4924,7 @@ var xxx_messageInfo_ScopeSelector proto.InternalMessageInfo func (m *ScopedResourceSelectorRequirement) Reset() { *m = ScopedResourceSelectorRequirement{} } func (*ScopedResourceSelectorRequirement) ProtoMessage() {} func (*ScopedResourceSelectorRequirement) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{171} + return fileDescriptor_83c10c24ec417dc9, []int{174} } func (m *ScopedResourceSelectorRequirement) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4868,7 +4952,7 @@ var xxx_messageInfo_ScopedResourceSelectorRequirement proto.InternalMessageInfo func (m *SeccompProfile) Reset() { *m = SeccompProfile{} } func (*SeccompProfile) ProtoMessage() {} func (*SeccompProfile) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{172} + return fileDescriptor_83c10c24ec417dc9, []int{175} } func (m *SeccompProfile) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4896,7 +4980,7 @@ var xxx_messageInfo_SeccompProfile proto.InternalMessageInfo func (m *Secret) Reset() { *m = Secret{} } func (*Secret) ProtoMessage() {} func (*Secret) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{173} + return fileDescriptor_83c10c24ec417dc9, []int{176} } func (m *Secret) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4924,7 +5008,7 @@ var xxx_messageInfo_Secret proto.InternalMessageInfo func (m *SecretEnvSource) Reset() { *m = SecretEnvSource{} } func (*SecretEnvSource) ProtoMessage() {} func (*SecretEnvSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{174} + return fileDescriptor_83c10c24ec417dc9, []int{177} } func (m *SecretEnvSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4952,7 +5036,7 @@ var xxx_messageInfo_SecretEnvSource proto.InternalMessageInfo func (m *SecretKeySelector) Reset() { *m = SecretKeySelector{} } func (*SecretKeySelector) ProtoMessage() {} func (*SecretKeySelector) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{175} + return fileDescriptor_83c10c24ec417dc9, []int{178} } func (m *SecretKeySelector) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4980,7 +5064,7 @@ var xxx_messageInfo_SecretKeySelector proto.InternalMessageInfo func (m *SecretList) Reset() { *m = SecretList{} } func (*SecretList) ProtoMessage() {} func (*SecretList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{176} + return fileDescriptor_83c10c24ec417dc9, []int{179} } func (m *SecretList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5008,7 +5092,7 @@ var xxx_messageInfo_SecretList proto.InternalMessageInfo func (m *SecretProjection) Reset() { *m = SecretProjection{} } func (*SecretProjection) ProtoMessage() {} func (*SecretProjection) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{177} + return fileDescriptor_83c10c24ec417dc9, []int{180} } func (m *SecretProjection) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5036,7 +5120,7 @@ var xxx_messageInfo_SecretProjection proto.InternalMessageInfo func (m *SecretReference) Reset() { *m = SecretReference{} } func (*SecretReference) ProtoMessage() {} func (*SecretReference) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{178} + return fileDescriptor_83c10c24ec417dc9, []int{181} } func (m *SecretReference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5064,7 +5148,7 @@ var xxx_messageInfo_SecretReference proto.InternalMessageInfo func (m *SecretVolumeSource) Reset() { *m = SecretVolumeSource{} } func (*SecretVolumeSource) ProtoMessage() {} func (*SecretVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{179} + return fileDescriptor_83c10c24ec417dc9, []int{182} } func (m *SecretVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5092,7 +5176,7 @@ var xxx_messageInfo_SecretVolumeSource proto.InternalMessageInfo func (m *SecurityContext) Reset() { *m = SecurityContext{} } func (*SecurityContext) ProtoMessage() {} func (*SecurityContext) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{180} + return fileDescriptor_83c10c24ec417dc9, []int{183} } func (m *SecurityContext) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5120,7 +5204,7 @@ var xxx_messageInfo_SecurityContext proto.InternalMessageInfo func (m *SerializedReference) Reset() { *m = SerializedReference{} } func (*SerializedReference) ProtoMessage() {} func (*SerializedReference) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{181} + return fileDescriptor_83c10c24ec417dc9, []int{184} } func (m *SerializedReference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5148,7 +5232,7 @@ var xxx_messageInfo_SerializedReference proto.InternalMessageInfo func (m *Service) Reset() { *m = Service{} } func (*Service) ProtoMessage() {} func (*Service) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{182} + return fileDescriptor_83c10c24ec417dc9, []int{185} } func (m *Service) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5176,7 +5260,7 @@ var xxx_messageInfo_Service proto.InternalMessageInfo func (m *ServiceAccount) Reset() { *m = ServiceAccount{} } func (*ServiceAccount) ProtoMessage() {} func (*ServiceAccount) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{183} + return fileDescriptor_83c10c24ec417dc9, []int{186} } func (m *ServiceAccount) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5204,7 +5288,7 @@ var xxx_messageInfo_ServiceAccount proto.InternalMessageInfo func (m *ServiceAccountList) Reset() { *m = ServiceAccountList{} } func (*ServiceAccountList) ProtoMessage() {} func (*ServiceAccountList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{184} + return fileDescriptor_83c10c24ec417dc9, []int{187} } func (m *ServiceAccountList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5232,7 +5316,7 @@ var xxx_messageInfo_ServiceAccountList proto.InternalMessageInfo func (m *ServiceAccountTokenProjection) Reset() { *m = ServiceAccountTokenProjection{} } func (*ServiceAccountTokenProjection) ProtoMessage() {} func (*ServiceAccountTokenProjection) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{185} + return fileDescriptor_83c10c24ec417dc9, []int{188} } func (m *ServiceAccountTokenProjection) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5260,7 +5344,7 @@ var xxx_messageInfo_ServiceAccountTokenProjection proto.InternalMessageInfo func (m *ServiceList) Reset() { *m = ServiceList{} } func (*ServiceList) ProtoMessage() {} func (*ServiceList) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{186} + return fileDescriptor_83c10c24ec417dc9, []int{189} } func (m *ServiceList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5288,7 +5372,7 @@ var xxx_messageInfo_ServiceList proto.InternalMessageInfo func (m *ServicePort) Reset() { *m = ServicePort{} } func (*ServicePort) ProtoMessage() {} func (*ServicePort) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{187} + return fileDescriptor_83c10c24ec417dc9, []int{190} } func (m *ServicePort) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5316,7 +5400,7 @@ var xxx_messageInfo_ServicePort proto.InternalMessageInfo func (m *ServiceProxyOptions) Reset() { *m = ServiceProxyOptions{} } func (*ServiceProxyOptions) ProtoMessage() {} func (*ServiceProxyOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{188} + return fileDescriptor_83c10c24ec417dc9, []int{191} } func (m *ServiceProxyOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5344,7 +5428,7 @@ var xxx_messageInfo_ServiceProxyOptions proto.InternalMessageInfo func (m *ServiceSpec) Reset() { *m = ServiceSpec{} } func (*ServiceSpec) ProtoMessage() {} func (*ServiceSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{189} + return fileDescriptor_83c10c24ec417dc9, []int{192} } func (m *ServiceSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5372,7 +5456,7 @@ var xxx_messageInfo_ServiceSpec proto.InternalMessageInfo func (m *ServiceStatus) Reset() { *m = ServiceStatus{} } func (*ServiceStatus) ProtoMessage() {} func (*ServiceStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{190} + return fileDescriptor_83c10c24ec417dc9, []int{193} } func (m *ServiceStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5400,7 +5484,7 @@ var xxx_messageInfo_ServiceStatus proto.InternalMessageInfo func (m *SessionAffinityConfig) Reset() { *m = SessionAffinityConfig{} } func (*SessionAffinityConfig) ProtoMessage() {} func (*SessionAffinityConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{191} + return fileDescriptor_83c10c24ec417dc9, []int{194} } func (m *SessionAffinityConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5428,7 +5512,7 @@ var xxx_messageInfo_SessionAffinityConfig proto.InternalMessageInfo func (m *StorageOSPersistentVolumeSource) Reset() { *m = StorageOSPersistentVolumeSource{} } func (*StorageOSPersistentVolumeSource) ProtoMessage() {} func (*StorageOSPersistentVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{192} + return fileDescriptor_83c10c24ec417dc9, []int{195} } func (m *StorageOSPersistentVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5456,7 +5540,7 @@ var xxx_messageInfo_StorageOSPersistentVolumeSource proto.InternalMessageInfo func (m *StorageOSVolumeSource) Reset() { *m = StorageOSVolumeSource{} } func (*StorageOSVolumeSource) ProtoMessage() {} func (*StorageOSVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{193} + return fileDescriptor_83c10c24ec417dc9, []int{196} } func (m *StorageOSVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5484,7 +5568,7 @@ var xxx_messageInfo_StorageOSVolumeSource proto.InternalMessageInfo func (m *Sysctl) Reset() { *m = Sysctl{} } func (*Sysctl) ProtoMessage() {} func (*Sysctl) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{194} + return fileDescriptor_83c10c24ec417dc9, []int{197} } func (m *Sysctl) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5512,7 +5596,7 @@ var xxx_messageInfo_Sysctl proto.InternalMessageInfo func (m *TCPSocketAction) Reset() { *m = TCPSocketAction{} } func (*TCPSocketAction) ProtoMessage() {} func (*TCPSocketAction) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{195} + return fileDescriptor_83c10c24ec417dc9, []int{198} } func (m *TCPSocketAction) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5540,7 +5624,7 @@ var xxx_messageInfo_TCPSocketAction proto.InternalMessageInfo func (m *Taint) Reset() { *m = Taint{} } func (*Taint) ProtoMessage() {} func (*Taint) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{196} + return fileDescriptor_83c10c24ec417dc9, []int{199} } func (m *Taint) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5568,7 +5652,7 @@ var xxx_messageInfo_Taint proto.InternalMessageInfo func (m *Toleration) Reset() { *m = Toleration{} } func (*Toleration) ProtoMessage() {} func (*Toleration) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{197} + return fileDescriptor_83c10c24ec417dc9, []int{200} } func (m *Toleration) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5596,7 +5680,7 @@ var xxx_messageInfo_Toleration proto.InternalMessageInfo func (m *TopologySelectorLabelRequirement) Reset() { *m = TopologySelectorLabelRequirement{} } func (*TopologySelectorLabelRequirement) ProtoMessage() {} func (*TopologySelectorLabelRequirement) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{198} + return fileDescriptor_83c10c24ec417dc9, []int{201} } func (m *TopologySelectorLabelRequirement) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5624,7 +5708,7 @@ var xxx_messageInfo_TopologySelectorLabelRequirement proto.InternalMessageInfo func (m *TopologySelectorTerm) Reset() { *m = TopologySelectorTerm{} } func (*TopologySelectorTerm) ProtoMessage() {} func (*TopologySelectorTerm) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{199} + return fileDescriptor_83c10c24ec417dc9, []int{202} } func (m *TopologySelectorTerm) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5652,7 +5736,7 @@ var xxx_messageInfo_TopologySelectorTerm proto.InternalMessageInfo func (m *TopologySpreadConstraint) Reset() { *m = TopologySpreadConstraint{} } func (*TopologySpreadConstraint) ProtoMessage() {} func (*TopologySpreadConstraint) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{200} + return fileDescriptor_83c10c24ec417dc9, []int{203} } func (m *TopologySpreadConstraint) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5680,7 +5764,7 @@ var xxx_messageInfo_TopologySpreadConstraint proto.InternalMessageInfo func (m *TypedLocalObjectReference) Reset() { *m = TypedLocalObjectReference{} } func (*TypedLocalObjectReference) ProtoMessage() {} func (*TypedLocalObjectReference) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{201} + return fileDescriptor_83c10c24ec417dc9, []int{204} } func (m *TypedLocalObjectReference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5708,7 +5792,7 @@ var xxx_messageInfo_TypedLocalObjectReference proto.InternalMessageInfo func (m *TypedObjectReference) Reset() { *m = TypedObjectReference{} } func (*TypedObjectReference) ProtoMessage() {} func (*TypedObjectReference) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{202} + return fileDescriptor_83c10c24ec417dc9, []int{205} } func (m *TypedObjectReference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5736,7 +5820,7 @@ var xxx_messageInfo_TypedObjectReference proto.InternalMessageInfo func (m *Volume) Reset() { *m = Volume{} } func (*Volume) ProtoMessage() {} func (*Volume) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{203} + return fileDescriptor_83c10c24ec417dc9, []int{206} } func (m *Volume) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5764,7 +5848,7 @@ var xxx_messageInfo_Volume proto.InternalMessageInfo func (m *VolumeDevice) Reset() { *m = VolumeDevice{} } func (*VolumeDevice) ProtoMessage() {} func (*VolumeDevice) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{204} + return fileDescriptor_83c10c24ec417dc9, []int{207} } func (m *VolumeDevice) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5792,7 +5876,7 @@ var xxx_messageInfo_VolumeDevice proto.InternalMessageInfo func (m *VolumeMount) Reset() { *m = VolumeMount{} } func (*VolumeMount) ProtoMessage() {} func (*VolumeMount) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{205} + return fileDescriptor_83c10c24ec417dc9, []int{208} } func (m *VolumeMount) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5820,7 +5904,7 @@ var xxx_messageInfo_VolumeMount proto.InternalMessageInfo func (m *VolumeNodeAffinity) Reset() { *m = VolumeNodeAffinity{} } func (*VolumeNodeAffinity) ProtoMessage() {} func (*VolumeNodeAffinity) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{206} + return fileDescriptor_83c10c24ec417dc9, []int{209} } func (m *VolumeNodeAffinity) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5848,7 +5932,7 @@ var xxx_messageInfo_VolumeNodeAffinity proto.InternalMessageInfo func (m *VolumeProjection) Reset() { *m = VolumeProjection{} } func (*VolumeProjection) ProtoMessage() {} func (*VolumeProjection) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{207} + return fileDescriptor_83c10c24ec417dc9, []int{210} } func (m *VolumeProjection) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5876,7 +5960,7 @@ var xxx_messageInfo_VolumeProjection proto.InternalMessageInfo func (m *VolumeSource) Reset() { *m = VolumeSource{} } func (*VolumeSource) ProtoMessage() {} func (*VolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{208} + return fileDescriptor_83c10c24ec417dc9, []int{211} } func (m *VolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5904,7 +5988,7 @@ var xxx_messageInfo_VolumeSource proto.InternalMessageInfo func (m *VsphereVirtualDiskVolumeSource) Reset() { *m = VsphereVirtualDiskVolumeSource{} } func (*VsphereVirtualDiskVolumeSource) ProtoMessage() {} func (*VsphereVirtualDiskVolumeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{209} + return fileDescriptor_83c10c24ec417dc9, []int{212} } func (m *VsphereVirtualDiskVolumeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5932,7 +6016,7 @@ var xxx_messageInfo_VsphereVirtualDiskVolumeSource proto.InternalMessageInfo func (m *WeightedPodAffinityTerm) Reset() { *m = WeightedPodAffinityTerm{} } func (*WeightedPodAffinityTerm) ProtoMessage() {} func (*WeightedPodAffinityTerm) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{210} + return fileDescriptor_83c10c24ec417dc9, []int{213} } func (m *WeightedPodAffinityTerm) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5960,7 +6044,7 @@ var xxx_messageInfo_WeightedPodAffinityTerm proto.InternalMessageInfo func (m *WindowsSecurityContextOptions) Reset() { *m = WindowsSecurityContextOptions{} } func (*WindowsSecurityContextOptions) ProtoMessage() {} func (*WindowsSecurityContextOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_83c10c24ec417dc9, []int{211} + return fileDescriptor_83c10c24ec417dc9, []int{214} } func (m *WindowsSecurityContextOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6003,6 +6087,7 @@ func init() { proto.RegisterType((*CephFSVolumeSource)(nil), "k8s.io.api.core.v1.CephFSVolumeSource") proto.RegisterType((*CinderPersistentVolumeSource)(nil), "k8s.io.api.core.v1.CinderPersistentVolumeSource") proto.RegisterType((*CinderVolumeSource)(nil), "k8s.io.api.core.v1.CinderVolumeSource") + proto.RegisterType((*ClaimSource)(nil), "k8s.io.api.core.v1.ClaimSource") proto.RegisterType((*ClientIPConfig)(nil), "k8s.io.api.core.v1.ClientIPConfig") proto.RegisterType((*ComponentCondition)(nil), "k8s.io.api.core.v1.ComponentCondition") proto.RegisterType((*ComponentStatus)(nil), "k8s.io.api.core.v1.ComponentStatus") @@ -6138,6 +6223,7 @@ func init() { proto.RegisterType((*PodPortForwardOptions)(nil), "k8s.io.api.core.v1.PodPortForwardOptions") proto.RegisterType((*PodProxyOptions)(nil), "k8s.io.api.core.v1.PodProxyOptions") proto.RegisterType((*PodReadinessGate)(nil), "k8s.io.api.core.v1.PodReadinessGate") + proto.RegisterType((*PodResourceClaim)(nil), "k8s.io.api.core.v1.PodResourceClaim") proto.RegisterType((*PodSchedulingGate)(nil), "k8s.io.api.core.v1.PodSchedulingGate") proto.RegisterType((*PodSecurityContext)(nil), "k8s.io.api.core.v1.PodSecurityContext") proto.RegisterType((*PodSignature)(nil), "k8s.io.api.core.v1.PodSignature") @@ -6167,6 +6253,7 @@ func init() { proto.RegisterType((*ReplicationControllerSpec)(nil), "k8s.io.api.core.v1.ReplicationControllerSpec") proto.RegisterMapType((map[string]string)(nil), "k8s.io.api.core.v1.ReplicationControllerSpec.SelectorEntry") proto.RegisterType((*ReplicationControllerStatus)(nil), "k8s.io.api.core.v1.ReplicationControllerStatus") + proto.RegisterType((*ResourceClaim)(nil), "k8s.io.api.core.v1.ResourceClaim") proto.RegisterType((*ResourceFieldSelector)(nil), "k8s.io.api.core.v1.ResourceFieldSelector") proto.RegisterType((*ResourceQuota)(nil), "k8s.io.api.core.v1.ResourceQuota") proto.RegisterType((*ResourceQuotaList)(nil), "k8s.io.api.core.v1.ResourceQuotaList") @@ -6233,910 +6320,917 @@ func init() { } var fileDescriptor_83c10c24ec417dc9 = []byte{ - // 14435 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x6b, 0x70, 0x24, 0xd7, - 0x79, 0x18, 0xaa, 0x9e, 0xc1, 0x6b, 0x3e, 0xbc, 0x0f, 0x76, 0x97, 0x58, 0x90, 0xbb, 0x58, 0x36, - 0xc9, 0xe5, 0x52, 0x24, 0x01, 0x2d, 0x1f, 0x12, 0x4d, 0x4a, 0xb4, 0x00, 0x0c, 0xb0, 0x0b, 0xee, - 0x02, 0x3b, 0x3c, 0x83, 0xdd, 0x95, 0x64, 0x4a, 0xa5, 0xc6, 0xcc, 0x01, 0xd0, 0xc2, 0x4c, 0xf7, - 0xb0, 0xbb, 0x07, 0xbb, 0xd8, 0x2b, 0xd7, 0xf5, 0x95, 0x9f, 0xb2, 0x7d, 0x6f, 0xa9, 0x6e, 0x39, - 0x8f, 0x92, 0x5d, 0xae, 0x94, 0xe3, 0xd8, 0x56, 0x94, 0xa4, 0xa2, 0xc8, 0xb1, 0x1d, 0xcb, 0x89, - 0x9d, 0xb7, 0x93, 0x1f, 0x8e, 0xe3, 0xaa, 0x58, 0xae, 0x72, 0x05, 0xb1, 0xd7, 0xa9, 0xb8, 0x54, - 0x95, 0xd8, 0x4e, 0x9c, 0x54, 0x25, 0x88, 0x13, 0xa7, 0xce, 0xb3, 0xcf, 0xe9, 0xc7, 0xcc, 0x60, - 0x89, 0x85, 0x28, 0x15, 0xff, 0xcd, 0x9c, 0xef, 0x3b, 0xdf, 0x39, 0x7d, 0x9e, 0xdf, 0xf9, 0x9e, - 0xf0, 0xda, 0xee, 0x2b, 0xe1, 0x9c, 0xeb, 0xcf, 0xef, 0xb6, 0x37, 0x49, 0xe0, 0x91, 0x88, 0x84, - 0xf3, 0x7b, 0xc4, 0xab, 0xfb, 0xc1, 0xbc, 0x00, 0x38, 0x2d, 0x77, 0xbe, 0xe6, 0x07, 0x64, 0x7e, - 0xef, 0xf2, 0xfc, 0x36, 0xf1, 0x48, 0xe0, 0x44, 0xa4, 0x3e, 0xd7, 0x0a, 0xfc, 0xc8, 0x47, 0x88, - 0xe3, 0xcc, 0x39, 0x2d, 0x77, 0x8e, 0xe2, 0xcc, 0xed, 0x5d, 0x9e, 0x79, 0x7e, 0xdb, 0x8d, 0x76, - 0xda, 0x9b, 0x73, 0x35, 0xbf, 0x39, 0xbf, 0xed, 0x6f, 0xfb, 0xf3, 0x0c, 0x75, 0xb3, 0xbd, 0xc5, - 0xfe, 0xb1, 0x3f, 0xec, 0x17, 0x27, 0x31, 0xf3, 0x52, 0xdc, 0x4c, 0xd3, 0xa9, 0xed, 0xb8, 0x1e, - 0x09, 0xf6, 0xe7, 0x5b, 0xbb, 0xdb, 0xac, 0xdd, 0x80, 0x84, 0x7e, 0x3b, 0xa8, 0x91, 0x64, 0xc3, - 0x1d, 0x6b, 0x85, 0xf3, 0x4d, 0x12, 0x39, 0x19, 0xdd, 0x9d, 0x99, 0xcf, 0xab, 0x15, 0xb4, 0xbd, - 0xc8, 0x6d, 0xa6, 0x9b, 0xf9, 0x60, 0xb7, 0x0a, 0x61, 0x6d, 0x87, 0x34, 0x9d, 0x54, 0xbd, 0x17, - 0xf3, 0xea, 0xb5, 0x23, 0xb7, 0x31, 0xef, 0x7a, 0x51, 0x18, 0x05, 0xc9, 0x4a, 0xf6, 0xd7, 0x2d, - 0xb8, 0xb0, 0x70, 0xbb, 0xba, 0xdc, 0x70, 0xc2, 0xc8, 0xad, 0x2d, 0x36, 0xfc, 0xda, 0x6e, 0x35, - 0xf2, 0x03, 0x72, 0xcb, 0x6f, 0xb4, 0x9b, 0xa4, 0xca, 0x06, 0x02, 0x3d, 0x07, 0x43, 0x7b, 0xec, - 0xff, 0x6a, 0x79, 0xda, 0xba, 0x60, 0x5d, 0x2a, 0x2d, 0x4e, 0xfc, 0xfa, 0xc1, 0xec, 0xfb, 0xee, - 0x1f, 0xcc, 0x0e, 0xdd, 0x12, 0xe5, 0x58, 0x61, 0xa0, 0x8b, 0x30, 0xb0, 0x15, 0x6e, 0xec, 0xb7, - 0xc8, 0x74, 0x81, 0xe1, 0x8e, 0x09, 0xdc, 0x81, 0x95, 0x2a, 0x2d, 0xc5, 0x02, 0x8a, 0xe6, 0xa1, - 0xd4, 0x72, 0x82, 0xc8, 0x8d, 0x5c, 0xdf, 0x9b, 0x2e, 0x5e, 0xb0, 0x2e, 0xf5, 0x2f, 0x4e, 0x0a, - 0xd4, 0x52, 0x45, 0x02, 0x70, 0x8c, 0x43, 0xbb, 0x11, 0x10, 0xa7, 0x7e, 0xc3, 0x6b, 0xec, 0x4f, - 0xf7, 0x5d, 0xb0, 0x2e, 0x0d, 0xc5, 0xdd, 0xc0, 0xa2, 0x1c, 0x2b, 0x0c, 0xfb, 0x8b, 0x05, 0x18, - 0x5a, 0xd8, 0xda, 0x72, 0x3d, 0x37, 0xda, 0x47, 0xb7, 0x60, 0xc4, 0xf3, 0xeb, 0x44, 0xfe, 0x67, - 0x5f, 0x31, 0xfc, 0xc2, 0x85, 0xb9, 0xf4, 0x52, 0x9a, 0x5b, 0xd7, 0xf0, 0x16, 0x27, 0xee, 0x1f, - 0xcc, 0x8e, 0xe8, 0x25, 0xd8, 0xa0, 0x83, 0x30, 0x0c, 0xb7, 0xfc, 0xba, 0x22, 0x5b, 0x60, 0x64, - 0x67, 0xb3, 0xc8, 0x56, 0x62, 0xb4, 0xc5, 0xf1, 0xfb, 0x07, 0xb3, 0xc3, 0x5a, 0x01, 0xd6, 0x89, - 0xa0, 0x4d, 0x18, 0xa7, 0x7f, 0xbd, 0xc8, 0x55, 0x74, 0x8b, 0x8c, 0xee, 0x13, 0x79, 0x74, 0x35, - 0xd4, 0xc5, 0xa9, 0xfb, 0x07, 0xb3, 0xe3, 0x89, 0x42, 0x9c, 0x24, 0x68, 0xdf, 0x83, 0xb1, 0x85, - 0x28, 0x72, 0x6a, 0x3b, 0xa4, 0xce, 0x67, 0x10, 0xbd, 0x04, 0x7d, 0x9e, 0xd3, 0x24, 0x62, 0x7e, - 0x2f, 0x88, 0x81, 0xed, 0x5b, 0x77, 0x9a, 0xe4, 0xf0, 0x60, 0x76, 0xe2, 0xa6, 0xe7, 0xbe, 0xdd, - 0x16, 0xab, 0x82, 0x96, 0x61, 0x86, 0x8d, 0x5e, 0x00, 0xa8, 0x93, 0x3d, 0xb7, 0x46, 0x2a, 0x4e, - 0xb4, 0x23, 0xe6, 0x1b, 0x89, 0xba, 0x50, 0x56, 0x10, 0xac, 0x61, 0xd9, 0x77, 0xa1, 0xb4, 0xb0, - 0xe7, 0xbb, 0xf5, 0x8a, 0x5f, 0x0f, 0xd1, 0x2e, 0x8c, 0xb7, 0x02, 0xb2, 0x45, 0x02, 0x55, 0x34, - 0x6d, 0x5d, 0x28, 0x5e, 0x1a, 0x7e, 0xe1, 0x52, 0xe6, 0xc7, 0x9a, 0xa8, 0xcb, 0x5e, 0x14, 0xec, - 0x2f, 0x3e, 0x22, 0xda, 0x1b, 0x4f, 0x40, 0x71, 0x92, 0xb2, 0xfd, 0x4f, 0x0a, 0x70, 0x7a, 0xe1, - 0x5e, 0x3b, 0x20, 0x65, 0x37, 0xdc, 0x4d, 0xae, 0xf0, 0xba, 0x1b, 0xee, 0xae, 0xc7, 0x23, 0xa0, - 0x96, 0x56, 0x59, 0x94, 0x63, 0x85, 0x81, 0x9e, 0x87, 0x41, 0xfa, 0xfb, 0x26, 0x5e, 0x15, 0x9f, - 0x3c, 0x25, 0x90, 0x87, 0xcb, 0x4e, 0xe4, 0x94, 0x39, 0x08, 0x4b, 0x1c, 0xb4, 0x06, 0xc3, 0x35, - 0xb6, 0x21, 0xb7, 0xd7, 0xfc, 0x3a, 0x61, 0x93, 0x59, 0x5a, 0x7c, 0x96, 0xa2, 0x2f, 0xc5, 0xc5, - 0x87, 0x07, 0xb3, 0xd3, 0xbc, 0x6f, 0x82, 0x84, 0x06, 0xc3, 0x7a, 0x7d, 0x64, 0xab, 0xfd, 0xd5, - 0xc7, 0x28, 0x41, 0xc6, 0xde, 0xba, 0xa4, 0x6d, 0x95, 0x7e, 0xb6, 0x55, 0x46, 0xb2, 0xb7, 0x09, - 0xba, 0x0c, 0x7d, 0xbb, 0xae, 0x57, 0x9f, 0x1e, 0x60, 0xb4, 0xce, 0xd1, 0x39, 0xbf, 0xe6, 0x7a, - 0xf5, 0xc3, 0x83, 0xd9, 0x49, 0xa3, 0x3b, 0xb4, 0x10, 0x33, 0x54, 0xfb, 0x4f, 0x2d, 0x98, 0x65, - 0xb0, 0x15, 0xb7, 0x41, 0x2a, 0x24, 0x08, 0xdd, 0x30, 0x22, 0x5e, 0x64, 0x0c, 0xe8, 0x0b, 0x00, - 0x21, 0xa9, 0x05, 0x24, 0xd2, 0x86, 0x54, 0x2d, 0x8c, 0xaa, 0x82, 0x60, 0x0d, 0x8b, 0x1e, 0x08, - 0xe1, 0x8e, 0x13, 0xb0, 0xf5, 0x25, 0x06, 0x56, 0x1d, 0x08, 0x55, 0x09, 0xc0, 0x31, 0x8e, 0x71, - 0x20, 0x14, 0xbb, 0x1d, 0x08, 0xe8, 0x23, 0x30, 0x1e, 0x37, 0x16, 0xb6, 0x9c, 0x9a, 0x1c, 0x40, - 0xb6, 0x65, 0xaa, 0x26, 0x08, 0x27, 0x71, 0xed, 0xbf, 0x6e, 0x89, 0xc5, 0x43, 0xbf, 0xfa, 0x5d, - 0xfe, 0xad, 0xf6, 0x2f, 0x59, 0x30, 0xb8, 0xe8, 0x7a, 0x75, 0xd7, 0xdb, 0x46, 0x9f, 0x86, 0x21, - 0x7a, 0x37, 0xd5, 0x9d, 0xc8, 0x11, 0xe7, 0xde, 0x07, 0xb4, 0xbd, 0xa5, 0xae, 0x8a, 0xb9, 0xd6, - 0xee, 0x36, 0x2d, 0x08, 0xe7, 0x28, 0x36, 0xdd, 0x6d, 0x37, 0x36, 0x3f, 0x43, 0x6a, 0xd1, 0x1a, - 0x89, 0x9c, 0xf8, 0x73, 0xe2, 0x32, 0xac, 0xa8, 0xa2, 0x6b, 0x30, 0x10, 0x39, 0xc1, 0x36, 0x89, - 0xc4, 0x01, 0x98, 0x79, 0x50, 0xf1, 0x9a, 0x98, 0xee, 0x48, 0xe2, 0xd5, 0x48, 0x7c, 0x2d, 0x6c, - 0xb0, 0xaa, 0x58, 0x90, 0xb0, 0xff, 0xd7, 0x20, 0x9c, 0x5d, 0xaa, 0xae, 0xe6, 0xac, 0xab, 0x8b, - 0x30, 0x50, 0x0f, 0xdc, 0x3d, 0x12, 0x88, 0x71, 0x56, 0x54, 0xca, 0xac, 0x14, 0x0b, 0x28, 0x7a, - 0x05, 0x46, 0xf8, 0x85, 0x74, 0xd5, 0xf1, 0xea, 0x0d, 0x39, 0xc4, 0xa7, 0x04, 0xf6, 0xc8, 0x2d, - 0x0d, 0x86, 0x0d, 0xcc, 0x23, 0x2e, 0xaa, 0x8b, 0x89, 0xcd, 0x98, 0x77, 0xd9, 0x7d, 0xde, 0x82, - 0x09, 0xde, 0xcc, 0x42, 0x14, 0x05, 0xee, 0x66, 0x3b, 0x22, 0xe1, 0x74, 0x3f, 0x3b, 0xe9, 0x96, - 0xb2, 0x46, 0x2b, 0x77, 0x04, 0xe6, 0x6e, 0x25, 0xa8, 0xf0, 0x43, 0x70, 0x5a, 0xb4, 0x3b, 0x91, - 0x04, 0xe3, 0x54, 0xb3, 0xe8, 0x7b, 0x2d, 0x98, 0xa9, 0xf9, 0x5e, 0x14, 0xf8, 0x8d, 0x06, 0x09, - 0x2a, 0xed, 0xcd, 0x86, 0x1b, 0xee, 0xf0, 0x75, 0x8a, 0xc9, 0x16, 0x3b, 0x09, 0x72, 0xe6, 0x50, - 0x21, 0x89, 0x39, 0x3c, 0x7f, 0xff, 0x60, 0x76, 0x66, 0x29, 0x97, 0x14, 0xee, 0xd0, 0x0c, 0xda, - 0x05, 0x44, 0xaf, 0xd2, 0x6a, 0xe4, 0x6c, 0x93, 0xb8, 0xf1, 0xc1, 0xde, 0x1b, 0x3f, 0x73, 0xff, - 0x60, 0x16, 0xad, 0xa7, 0x48, 0xe0, 0x0c, 0xb2, 0xe8, 0x6d, 0x38, 0x45, 0x4b, 0x53, 0xdf, 0x3a, - 0xd4, 0x7b, 0x73, 0xd3, 0xf7, 0x0f, 0x66, 0x4f, 0xad, 0x67, 0x10, 0xc1, 0x99, 0xa4, 0xd1, 0xf7, - 0x58, 0x70, 0x36, 0xfe, 0xfc, 0xe5, 0xbb, 0x2d, 0xc7, 0xab, 0xc7, 0x0d, 0x97, 0x7a, 0x6f, 0x98, - 0x9e, 0xc9, 0x67, 0x97, 0xf2, 0x28, 0xe1, 0xfc, 0x46, 0x90, 0x07, 0x53, 0xb4, 0x6b, 0xc9, 0xb6, - 0xa1, 0xf7, 0xb6, 0x1f, 0xb9, 0x7f, 0x30, 0x3b, 0xb5, 0x9e, 0xa6, 0x81, 0xb3, 0x08, 0xcf, 0x2c, - 0xc1, 0xe9, 0xcc, 0xd5, 0x89, 0x26, 0xa0, 0xb8, 0x4b, 0x38, 0xd7, 0x55, 0xc2, 0xf4, 0x27, 0x3a, - 0x05, 0xfd, 0x7b, 0x4e, 0xa3, 0x2d, 0x36, 0x26, 0xe6, 0x7f, 0x5e, 0x2d, 0xbc, 0x62, 0xd9, 0xff, - 0xb4, 0x08, 0xe3, 0x4b, 0xd5, 0xd5, 0x07, 0xda, 0xf5, 0xfa, 0xb5, 0x57, 0xe8, 0x78, 0xed, 0xc5, - 0x97, 0x68, 0x31, 0xf7, 0x12, 0xfd, 0xbf, 0x33, 0xb6, 0x6c, 0x1f, 0xdb, 0xb2, 0xdf, 0x91, 0xb3, - 0x65, 0x8f, 0x79, 0xa3, 0xee, 0xe5, 0xac, 0xda, 0x7e, 0x36, 0x81, 0x99, 0x1c, 0xd2, 0x75, 0xbf, - 0xe6, 0x34, 0x92, 0x47, 0xed, 0x11, 0x97, 0xee, 0xf1, 0xcc, 0x63, 0x0d, 0x46, 0x96, 0x9c, 0x96, - 0xb3, 0xe9, 0x36, 0xdc, 0xc8, 0x25, 0x21, 0x7a, 0x1a, 0x8a, 0x4e, 0xbd, 0xce, 0xb8, 0xbb, 0xd2, - 0xe2, 0xe9, 0xfb, 0x07, 0xb3, 0xc5, 0x85, 0x3a, 0x65, 0x33, 0x40, 0x61, 0xed, 0x63, 0x8a, 0x81, - 0xde, 0x0f, 0x7d, 0xf5, 0xc0, 0x6f, 0x4d, 0x17, 0x18, 0x26, 0xdd, 0xe5, 0x7d, 0xe5, 0xc0, 0x6f, - 0x25, 0x50, 0x19, 0x8e, 0xfd, 0x6b, 0x05, 0x78, 0x6c, 0x89, 0xb4, 0x76, 0x56, 0xaa, 0x39, 0xf7, - 0xc5, 0x25, 0x18, 0x6a, 0xfa, 0x9e, 0x1b, 0xf9, 0x41, 0x28, 0x9a, 0x66, 0x2b, 0x62, 0x4d, 0x94, - 0x61, 0x05, 0x45, 0x17, 0xa0, 0xaf, 0x15, 0x33, 0xb1, 0x23, 0x92, 0x01, 0x66, 0xec, 0x2b, 0x83, - 0x50, 0x8c, 0x76, 0x48, 0x02, 0xb1, 0x62, 0x14, 0xc6, 0xcd, 0x90, 0x04, 0x98, 0x41, 0x62, 0x4e, - 0x80, 0xf2, 0x08, 0xe2, 0x46, 0x48, 0x70, 0x02, 0x14, 0x82, 0x35, 0x2c, 0x54, 0x81, 0x52, 0x98, - 0x98, 0xd9, 0x9e, 0xb6, 0xe6, 0x28, 0x63, 0x15, 0xd4, 0x4c, 0xc6, 0x44, 0x8c, 0x1b, 0x6c, 0xa0, - 0x2b, 0xab, 0xf0, 0xb5, 0x02, 0x20, 0x3e, 0x84, 0xdf, 0x62, 0x03, 0x77, 0x33, 0x3d, 0x70, 0xbd, - 0x6f, 0x89, 0xe3, 0x1a, 0xbd, 0xff, 0x6a, 0xc1, 0x63, 0x4b, 0xae, 0x57, 0x27, 0x41, 0xce, 0x02, - 0x7c, 0x38, 0x6f, 0xe7, 0xa3, 0x31, 0x29, 0xc6, 0x12, 0xeb, 0x3b, 0x86, 0x25, 0x66, 0xff, 0xb1, - 0x05, 0x88, 0x7f, 0xf6, 0xbb, 0xee, 0x63, 0x6f, 0xa6, 0x3f, 0xf6, 0x18, 0x96, 0x85, 0x7d, 0x1d, - 0xc6, 0x96, 0x1a, 0x2e, 0xf1, 0xa2, 0xd5, 0xca, 0x92, 0xef, 0x6d, 0xb9, 0xdb, 0xe8, 0x55, 0x18, - 0x8b, 0xdc, 0x26, 0xf1, 0xdb, 0x51, 0x95, 0xd4, 0x7c, 0x8f, 0xbd, 0x5c, 0xad, 0x4b, 0xfd, 0x8b, - 0xe8, 0xfe, 0xc1, 0xec, 0xd8, 0x86, 0x01, 0xc1, 0x09, 0x4c, 0xfb, 0x77, 0xe9, 0xf8, 0xf9, 0xcd, - 0x96, 0xef, 0x11, 0x2f, 0x5a, 0xf2, 0xbd, 0x3a, 0x97, 0x70, 0xbc, 0x0a, 0x7d, 0x11, 0x1d, 0x0f, - 0x3e, 0x76, 0x17, 0xe5, 0x46, 0xa1, 0xa3, 0x70, 0x78, 0x30, 0x7b, 0x26, 0x5d, 0x83, 0x8d, 0x13, - 0xab, 0x83, 0xbe, 0x03, 0x06, 0xc2, 0xc8, 0x89, 0xda, 0xa1, 0x18, 0xcd, 0xc7, 0xe5, 0x68, 0x56, - 0x59, 0xe9, 0xe1, 0xc1, 0xec, 0xb8, 0xaa, 0xc6, 0x8b, 0xb0, 0xa8, 0x80, 0x9e, 0x81, 0xc1, 0x26, - 0x09, 0x43, 0x67, 0x5b, 0xde, 0x86, 0xe3, 0xa2, 0xee, 0xe0, 0x1a, 0x2f, 0xc6, 0x12, 0x8e, 0x9e, - 0x80, 0x7e, 0x12, 0x04, 0x7e, 0x20, 0xf6, 0xe8, 0xa8, 0x40, 0xec, 0x5f, 0xa6, 0x85, 0x98, 0xc3, - 0xec, 0x7f, 0x65, 0xc1, 0xb8, 0xea, 0x2b, 0x6f, 0xeb, 0x04, 0x5e, 0x21, 0x9f, 0x00, 0xa8, 0xc9, - 0x0f, 0x0c, 0xd9, 0xed, 0x31, 0xfc, 0xc2, 0xc5, 0xcc, 0x8b, 0x3a, 0x35, 0x8c, 0x31, 0x65, 0x55, - 0x14, 0x62, 0x8d, 0x9a, 0xfd, 0xf7, 0x2d, 0x98, 0x4a, 0x7c, 0xd1, 0x75, 0x37, 0x8c, 0xd0, 0x5b, - 0xa9, 0xaf, 0x9a, 0xeb, 0xed, 0xab, 0x68, 0x6d, 0xf6, 0x4d, 0x6a, 0x29, 0xcb, 0x12, 0xed, 0x8b, - 0xae, 0x42, 0xbf, 0x1b, 0x91, 0xa6, 0xfc, 0x98, 0x27, 0x3a, 0x7e, 0x0c, 0xef, 0x55, 0x3c, 0x23, - 0xab, 0xb4, 0x26, 0xe6, 0x04, 0xec, 0x5f, 0x2b, 0x42, 0x89, 0x2f, 0xdb, 0x35, 0xa7, 0x75, 0x02, - 0x73, 0xf1, 0x2c, 0x94, 0xdc, 0x66, 0xb3, 0x1d, 0x39, 0x9b, 0xe2, 0x38, 0x1f, 0xe2, 0x5b, 0x6b, - 0x55, 0x16, 0xe2, 0x18, 0x8e, 0x56, 0xa1, 0x8f, 0x75, 0x85, 0x7f, 0xe5, 0xd3, 0xd9, 0x5f, 0x29, - 0xfa, 0x3e, 0x57, 0x76, 0x22, 0x87, 0x73, 0x52, 0xea, 0x1e, 0xa1, 0x45, 0x98, 0x91, 0x40, 0x0e, - 0xc0, 0xa6, 0xeb, 0x39, 0xc1, 0x3e, 0x2d, 0x9b, 0x2e, 0x32, 0x82, 0xcf, 0x77, 0x26, 0xb8, 0xa8, - 0xf0, 0x39, 0x59, 0xf5, 0x61, 0x31, 0x00, 0x6b, 0x44, 0x67, 0x3e, 0x04, 0x25, 0x85, 0x7c, 0x14, - 0x86, 0x68, 0xe6, 0x23, 0x30, 0x9e, 0x68, 0xab, 0x5b, 0xf5, 0x11, 0x9d, 0x9f, 0xfa, 0x65, 0x76, - 0x64, 0x88, 0x5e, 0x2f, 0x7b, 0x7b, 0xe2, 0xc8, 0xbd, 0x07, 0xa7, 0x1a, 0x19, 0x27, 0x99, 0x98, - 0xd7, 0xde, 0x4f, 0xbe, 0xc7, 0xc4, 0x67, 0x9f, 0xca, 0x82, 0xe2, 0xcc, 0x36, 0x28, 0x8f, 0xe0, - 0xb7, 0xe8, 0x06, 0x71, 0x1a, 0x3a, 0xbb, 0x7d, 0x43, 0x94, 0x61, 0x05, 0xa5, 0xe7, 0xdd, 0x29, - 0xd5, 0xf9, 0x6b, 0x64, 0xbf, 0x4a, 0x1a, 0xa4, 0x16, 0xf9, 0xc1, 0x37, 0xb5, 0xfb, 0xe7, 0xf8, - 0xe8, 0xf3, 0xe3, 0x72, 0x58, 0x10, 0x28, 0x5e, 0x23, 0xfb, 0x7c, 0x2a, 0xf4, 0xaf, 0x2b, 0x76, - 0xfc, 0xba, 0xaf, 0x58, 0x30, 0xaa, 0xbe, 0xee, 0x04, 0xce, 0x85, 0x45, 0xf3, 0x5c, 0x38, 0xd7, - 0x71, 0x81, 0xe7, 0x9c, 0x08, 0x5f, 0x2b, 0xc0, 0x59, 0x85, 0x43, 0xdf, 0x06, 0xfc, 0x8f, 0x58, - 0x55, 0xf3, 0x50, 0xf2, 0x94, 0x94, 0xcc, 0x32, 0xc5, 0x53, 0xb1, 0x8c, 0x2c, 0xc6, 0xa1, 0x2c, - 0x9e, 0x17, 0x8b, 0xb2, 0x46, 0x74, 0xf1, 0xb1, 0x10, 0x15, 0x2f, 0x42, 0xb1, 0xed, 0xd6, 0xc5, - 0x05, 0xf3, 0x01, 0x39, 0xda, 0x37, 0x57, 0xcb, 0x87, 0x07, 0xb3, 0x8f, 0xe7, 0xa9, 0x2e, 0xe8, - 0xcd, 0x16, 0xce, 0xdd, 0x5c, 0x2d, 0x63, 0x5a, 0x19, 0x2d, 0xc0, 0xb8, 0xd4, 0xce, 0xdc, 0xa2, - 0xec, 0x96, 0xef, 0x89, 0x7b, 0x48, 0xc9, 0x80, 0xb1, 0x09, 0xc6, 0x49, 0x7c, 0x54, 0x86, 0x89, - 0xdd, 0xf6, 0x26, 0x69, 0x90, 0x88, 0x7f, 0xf0, 0x35, 0xc2, 0x25, 0xa4, 0xa5, 0xf8, 0x65, 0x76, - 0x2d, 0x01, 0xc7, 0xa9, 0x1a, 0xf6, 0x9f, 0xb3, 0xfb, 0x40, 0x8c, 0x5e, 0x25, 0xf0, 0xe9, 0xc2, - 0xa2, 0xd4, 0xbf, 0x99, 0xcb, 0xb9, 0x97, 0x55, 0x71, 0x8d, 0xec, 0x6f, 0xf8, 0x94, 0x33, 0xcf, - 0x5e, 0x15, 0xc6, 0x9a, 0xef, 0xeb, 0xb8, 0xe6, 0x7f, 0xbe, 0x00, 0xa7, 0xd5, 0x08, 0x18, 0x4c, - 0xe0, 0xb7, 0xfa, 0x18, 0x5c, 0x86, 0xe1, 0x3a, 0xd9, 0x72, 0xda, 0x8d, 0x48, 0x89, 0xeb, 0xfb, - 0xb9, 0xca, 0xa6, 0x1c, 0x17, 0x63, 0x1d, 0xe7, 0x08, 0xc3, 0xf6, 0xdf, 0x86, 0xd9, 0x45, 0x1c, - 0x39, 0x74, 0x8d, 0xab, 0x5d, 0x63, 0xe5, 0xee, 0x9a, 0x27, 0xa0, 0xdf, 0x6d, 0x52, 0xc6, 0xac, - 0x60, 0xf2, 0x5b, 0xab, 0xb4, 0x10, 0x73, 0x18, 0x7a, 0x0a, 0x06, 0x6b, 0x7e, 0xb3, 0xe9, 0x78, - 0x75, 0x76, 0xe5, 0x95, 0x16, 0x87, 0x29, 0xef, 0xb6, 0xc4, 0x8b, 0xb0, 0x84, 0xa1, 0xc7, 0xa0, - 0xcf, 0x09, 0xb6, 0xb9, 0x0c, 0xa3, 0xb4, 0x38, 0x44, 0x5b, 0x5a, 0x08, 0xb6, 0x43, 0xcc, 0x4a, - 0xe9, 0x13, 0xec, 0x8e, 0x1f, 0xec, 0xba, 0xde, 0x76, 0xd9, 0x0d, 0xc4, 0x96, 0x50, 0x77, 0xe1, - 0x6d, 0x05, 0xc1, 0x1a, 0x16, 0x5a, 0x81, 0xfe, 0x96, 0x1f, 0x44, 0xe1, 0xf4, 0x00, 0x1b, 0xee, - 0xc7, 0x73, 0x0e, 0x22, 0xfe, 0xb5, 0x15, 0x3f, 0x88, 0xe2, 0x0f, 0xa0, 0xff, 0x42, 0xcc, 0xab, - 0xa3, 0xeb, 0x30, 0x48, 0xbc, 0xbd, 0x95, 0xc0, 0x6f, 0x4e, 0x4f, 0xe5, 0x53, 0x5a, 0xe6, 0x28, - 0x7c, 0x99, 0xc5, 0x3c, 0xaa, 0x28, 0xc6, 0x92, 0x04, 0xfa, 0x0e, 0x28, 0x12, 0x6f, 0x6f, 0x7a, - 0x90, 0x51, 0x9a, 0xc9, 0xa1, 0x74, 0xcb, 0x09, 0xe2, 0x33, 0x7f, 0xd9, 0xdb, 0xc3, 0xb4, 0x0e, - 0xfa, 0x38, 0x94, 0xe4, 0x81, 0x11, 0x0a, 0xe1, 0x60, 0xe6, 0x82, 0x95, 0xc7, 0x0c, 0x26, 0x6f, - 0xb7, 0xdd, 0x80, 0x34, 0x89, 0x17, 0x85, 0xf1, 0x09, 0x29, 0xa1, 0x21, 0x8e, 0xa9, 0xa1, 0x8f, - 0x4b, 0x89, 0xf4, 0x9a, 0xdf, 0xf6, 0xa2, 0x70, 0xba, 0xc4, 0xba, 0x97, 0xa9, 0x2b, 0xbc, 0x15, - 0xe3, 0x25, 0x45, 0xd6, 0xbc, 0x32, 0x36, 0x48, 0xa1, 0x4f, 0xc2, 0x28, 0xff, 0xcf, 0x35, 0x6e, - 0xe1, 0xf4, 0x69, 0x46, 0xfb, 0x42, 0x3e, 0x6d, 0x8e, 0xb8, 0x78, 0x5a, 0x10, 0x1f, 0xd5, 0x4b, - 0x43, 0x6c, 0x52, 0x43, 0x18, 0x46, 0x1b, 0xee, 0x1e, 0xf1, 0x48, 0x18, 0x56, 0x02, 0x7f, 0x93, - 0x08, 0x01, 0xe2, 0xd9, 0x6c, 0x0d, 0x9d, 0xbf, 0x49, 0x16, 0x27, 0x29, 0xcd, 0xeb, 0x7a, 0x1d, - 0x6c, 0x92, 0x40, 0x37, 0x61, 0x8c, 0xbe, 0xd8, 0xdc, 0x98, 0xe8, 0x70, 0x37, 0xa2, 0xec, 0x5d, - 0x85, 0x8d, 0x4a, 0x38, 0x41, 0x04, 0xdd, 0x80, 0x91, 0x30, 0x72, 0x82, 0xa8, 0xdd, 0xe2, 0x44, - 0xcf, 0x74, 0x23, 0xca, 0x14, 0xbc, 0x55, 0xad, 0x0a, 0x36, 0x08, 0xa0, 0x37, 0xa0, 0xd4, 0x70, - 0xb7, 0x48, 0x6d, 0xbf, 0xd6, 0x20, 0xd3, 0x23, 0x8c, 0x5a, 0xe6, 0xa1, 0x72, 0x5d, 0x22, 0x71, - 0x3e, 0x57, 0xfd, 0xc5, 0x71, 0x75, 0x74, 0x0b, 0xce, 0x44, 0x24, 0x68, 0xba, 0x9e, 0x43, 0x0f, - 0x03, 0xf1, 0xb4, 0x62, 0x8a, 0xd3, 0x51, 0xb6, 0xdb, 0xce, 0x8b, 0xd9, 0x38, 0xb3, 0x91, 0x89, - 0x85, 0x73, 0x6a, 0xa3, 0xbb, 0x30, 0x9d, 0x01, 0xf1, 0x1b, 0x6e, 0x6d, 0x7f, 0xfa, 0x14, 0xa3, - 0xfc, 0x61, 0x41, 0x79, 0x7a, 0x23, 0x07, 0xef, 0xb0, 0x03, 0x0c, 0xe7, 0x52, 0x47, 0x37, 0x60, - 0x9c, 0x9d, 0x40, 0x95, 0x76, 0xa3, 0x21, 0x1a, 0x1c, 0x63, 0x0d, 0x3e, 0x25, 0xef, 0xe3, 0x55, - 0x13, 0x7c, 0x78, 0x30, 0x0b, 0xf1, 0x3f, 0x9c, 0xac, 0x8d, 0x36, 0x99, 0x8e, 0xae, 0x1d, 0xb8, - 0xd1, 0x3e, 0x3d, 0x37, 0xc8, 0xdd, 0x68, 0x7a, 0xbc, 0xa3, 0xbc, 0x42, 0x47, 0x55, 0x8a, 0x3c, - 0xbd, 0x10, 0x27, 0x09, 0xd2, 0x23, 0x35, 0x8c, 0xea, 0xae, 0x37, 0x3d, 0xc1, 0xdf, 0x25, 0xf2, - 0x44, 0xaa, 0xd2, 0x42, 0xcc, 0x61, 0x4c, 0x3f, 0x47, 0x7f, 0xdc, 0xa0, 0x37, 0xd7, 0x24, 0x43, - 0x8c, 0xf5, 0x73, 0x12, 0x80, 0x63, 0x1c, 0xca, 0x4c, 0x46, 0xd1, 0xfe, 0x34, 0x62, 0xa8, 0xea, - 0x60, 0xd9, 0xd8, 0xf8, 0x38, 0xa6, 0xe5, 0xf6, 0x26, 0x8c, 0xa9, 0x83, 0x90, 0x8d, 0x09, 0x9a, - 0x85, 0x7e, 0xc6, 0x3e, 0x09, 0xe9, 0x5a, 0x89, 0x76, 0x81, 0xb1, 0x56, 0x98, 0x97, 0xb3, 0x2e, - 0xb8, 0xf7, 0xc8, 0xe2, 0x7e, 0x44, 0xf8, 0x9b, 0xbe, 0xa8, 0x75, 0x41, 0x02, 0x70, 0x8c, 0x63, - 0xff, 0x6f, 0xce, 0x86, 0xc6, 0xa7, 0x6d, 0x0f, 0xf7, 0xcb, 0x73, 0x30, 0xb4, 0xe3, 0x87, 0x11, - 0xc5, 0x66, 0x6d, 0xf4, 0xc7, 0x8c, 0xe7, 0x55, 0x51, 0x8e, 0x15, 0x06, 0x7a, 0x0d, 0x46, 0x6b, - 0x7a, 0x03, 0xe2, 0x72, 0x54, 0xc7, 0x88, 0xd1, 0x3a, 0x36, 0x71, 0xd1, 0x2b, 0x30, 0xc4, 0x6c, - 0x4e, 0x6a, 0x7e, 0x43, 0x70, 0x6d, 0xf2, 0x86, 0x1f, 0xaa, 0x88, 0xf2, 0x43, 0xed, 0x37, 0x56, - 0xd8, 0xe8, 0x22, 0x0c, 0xd0, 0x2e, 0xac, 0x56, 0xc4, 0xb5, 0xa4, 0x04, 0x45, 0x57, 0x59, 0x29, - 0x16, 0x50, 0xfb, 0xff, 0x2f, 0x68, 0xa3, 0x4c, 0xdf, 0xc3, 0x04, 0x55, 0x60, 0xf0, 0x8e, 0xe3, - 0x46, 0xae, 0xb7, 0x2d, 0xf8, 0x8f, 0x67, 0x3a, 0xde, 0x51, 0xac, 0xd2, 0x6d, 0x5e, 0x81, 0xdf, - 0xa2, 0xe2, 0x0f, 0x96, 0x64, 0x28, 0xc5, 0xa0, 0xed, 0x79, 0x94, 0x62, 0xa1, 0x57, 0x8a, 0x98, - 0x57, 0xe0, 0x14, 0xc5, 0x1f, 0x2c, 0xc9, 0xa0, 0xb7, 0x00, 0xe4, 0x0e, 0x23, 0x75, 0x61, 0xeb, - 0xf1, 0x5c, 0x77, 0xa2, 0x1b, 0xaa, 0xce, 0xe2, 0x18, 0xbd, 0xa3, 0xe3, 0xff, 0x58, 0xa3, 0x67, - 0x47, 0x8c, 0x4f, 0x4b, 0x77, 0x06, 0x7d, 0x17, 0x5d, 0xe2, 0x4e, 0x10, 0x91, 0xfa, 0x42, 0x24, - 0x06, 0xe7, 0xfd, 0xbd, 0x3d, 0x52, 0x36, 0xdc, 0x26, 0xd1, 0xb7, 0x83, 0x20, 0x82, 0x63, 0x7a, - 0xf6, 0x2f, 0x16, 0x61, 0x3a, 0xaf, 0xbb, 0x74, 0xd1, 0x91, 0xbb, 0x6e, 0xb4, 0x44, 0xd9, 0x2b, - 0xcb, 0x5c, 0x74, 0xcb, 0xa2, 0x1c, 0x2b, 0x0c, 0x3a, 0xfb, 0xa1, 0xbb, 0x2d, 0xdf, 0x98, 0xfd, - 0xf1, 0xec, 0x57, 0x59, 0x29, 0x16, 0x50, 0x8a, 0x17, 0x10, 0x27, 0x14, 0xc6, 0x44, 0xda, 0x2a, - 0xc1, 0xac, 0x14, 0x0b, 0xa8, 0x2e, 0xed, 0xea, 0xeb, 0x22, 0xed, 0x32, 0x86, 0xa8, 0xff, 0x78, - 0x87, 0x08, 0x7d, 0x0a, 0x60, 0xcb, 0xf5, 0xdc, 0x70, 0x87, 0x51, 0x1f, 0x38, 0x32, 0x75, 0xc5, - 0x9c, 0xad, 0x28, 0x2a, 0x58, 0xa3, 0x88, 0x5e, 0x86, 0x61, 0xb5, 0x01, 0x57, 0xcb, 0x4c, 0xb3, - 0xaa, 0x59, 0xaa, 0xc4, 0xa7, 0x51, 0x19, 0xeb, 0x78, 0xf6, 0x67, 0x92, 0xeb, 0x45, 0xec, 0x00, - 0x6d, 0x7c, 0xad, 0x5e, 0xc7, 0xb7, 0xd0, 0x79, 0x7c, 0xed, 0x6f, 0x14, 0x61, 0xdc, 0x68, 0xac, - 0x1d, 0xf6, 0x70, 0x66, 0x5d, 0xa1, 0x07, 0xb8, 0x13, 0x11, 0xb1, 0xff, 0xec, 0xee, 0x5b, 0x45, - 0x3f, 0xe4, 0xe9, 0x0e, 0xe0, 0xf5, 0xd1, 0xa7, 0xa0, 0xd4, 0x70, 0x42, 0x26, 0x39, 0x23, 0x62, - 0xdf, 0xf5, 0x42, 0x2c, 0x7e, 0x98, 0x38, 0x61, 0xa4, 0xdd, 0x9a, 0x9c, 0x76, 0x4c, 0x92, 0xde, - 0x34, 0x94, 0x3f, 0x91, 0xd6, 0x6a, 0xaa, 0x13, 0x94, 0x89, 0xd9, 0xc7, 0x1c, 0x86, 0x5e, 0x81, - 0x91, 0x80, 0xb0, 0x55, 0xb1, 0x44, 0xb9, 0x39, 0xb6, 0xcc, 0xfa, 0x63, 0xb6, 0x0f, 0x6b, 0x30, - 0x6c, 0x60, 0xc6, 0x6f, 0x83, 0x81, 0x0e, 0x6f, 0x83, 0x67, 0x60, 0x90, 0xfd, 0x50, 0x2b, 0x40, - 0xcd, 0xc6, 0x2a, 0x2f, 0xc6, 0x12, 0x9e, 0x5c, 0x30, 0x43, 0xbd, 0x2d, 0x18, 0xfa, 0xfa, 0x10, - 0x8b, 0x9a, 0x69, 0xb5, 0x87, 0xf8, 0x29, 0x27, 0x96, 0x3c, 0x96, 0x30, 0xfb, 0xfd, 0x30, 0x56, - 0x76, 0x48, 0xd3, 0xf7, 0x96, 0xbd, 0x7a, 0xcb, 0x77, 0xbd, 0x08, 0x4d, 0x43, 0x1f, 0xbb, 0x44, - 0xf8, 0x11, 0xd0, 0x47, 0x1b, 0xc2, 0xac, 0xc4, 0xde, 0x86, 0xd3, 0x65, 0xff, 0x8e, 0x77, 0xc7, - 0x09, 0xea, 0x0b, 0x95, 0x55, 0xed, 0x7d, 0xbd, 0x2e, 0xdf, 0x77, 0xdc, 0x48, 0x2c, 0xf3, 0xe8, - 0xd5, 0x6a, 0x72, 0xb6, 0x76, 0xc5, 0x6d, 0x90, 0x1c, 0x29, 0xc8, 0x5f, 0x2a, 0x18, 0x2d, 0xc5, - 0xf8, 0x4a, 0xab, 0x65, 0xe5, 0x6a, 0xb5, 0xde, 0x84, 0xa1, 0x2d, 0x97, 0x34, 0xea, 0x98, 0x6c, - 0x89, 0x95, 0xf8, 0x74, 0xbe, 0xdd, 0xcb, 0x0a, 0xc5, 0x94, 0x52, 0x2f, 0xfe, 0x3a, 0x5c, 0x11, - 0x95, 0xb1, 0x22, 0x83, 0x76, 0x61, 0x42, 0x3e, 0x18, 0x24, 0x54, 0xac, 0xcb, 0x67, 0x3a, 0xbd, - 0x42, 0x4c, 0xe2, 0xa7, 0xee, 0x1f, 0xcc, 0x4e, 0xe0, 0x04, 0x19, 0x9c, 0x22, 0x4c, 0x9f, 0x83, - 0x4d, 0x7a, 0x02, 0xf7, 0xb1, 0xe1, 0x67, 0xcf, 0x41, 0xf6, 0xb2, 0x65, 0xa5, 0xf6, 0x4f, 0x58, - 0xf0, 0x48, 0x6a, 0x64, 0xc4, 0x0b, 0xff, 0x98, 0x67, 0x21, 0xf9, 0xe2, 0x2e, 0x74, 0x7f, 0x71, - 0xdb, 0x7f, 0xc3, 0x82, 0x53, 0xcb, 0xcd, 0x56, 0xb4, 0x5f, 0x76, 0x4d, 0x15, 0xd4, 0x87, 0x60, - 0xa0, 0x49, 0xea, 0x6e, 0xbb, 0x29, 0x66, 0x6e, 0x56, 0x9e, 0x52, 0x6b, 0xac, 0xf4, 0xf0, 0x60, - 0x76, 0xb4, 0x1a, 0xf9, 0x81, 0xb3, 0x4d, 0x78, 0x01, 0x16, 0xe8, 0xec, 0xac, 0x77, 0xef, 0x91, - 0xeb, 0x6e, 0xd3, 0x95, 0x76, 0x4c, 0x1d, 0x65, 0x76, 0x73, 0x72, 0x40, 0xe7, 0xde, 0x6c, 0x3b, - 0x5e, 0xe4, 0x46, 0xfb, 0x42, 0x7b, 0x24, 0x89, 0xe0, 0x98, 0x9e, 0xfd, 0x75, 0x0b, 0xc6, 0xe5, - 0xba, 0x5f, 0xa8, 0xd7, 0x03, 0x12, 0x86, 0x68, 0x06, 0x0a, 0x6e, 0x4b, 0xf4, 0x12, 0x44, 0x2f, - 0x0b, 0xab, 0x15, 0x5c, 0x70, 0x5b, 0x92, 0x2d, 0x63, 0x07, 0x61, 0xd1, 0x54, 0xa4, 0x5d, 0x15, - 0xe5, 0x58, 0x61, 0xa0, 0x4b, 0x30, 0xe4, 0xf9, 0x75, 0x6e, 0x4b, 0xc6, 0xaf, 0x34, 0xb6, 0xc0, - 0xd6, 0x45, 0x19, 0x56, 0x50, 0x54, 0x81, 0x12, 0x37, 0xb3, 0x8a, 0x17, 0x6d, 0x4f, 0xc6, 0x5a, - 0xec, 0xcb, 0x36, 0x64, 0x4d, 0x1c, 0x13, 0xb1, 0x7f, 0xd5, 0x82, 0x11, 0xf9, 0x65, 0x3d, 0xf2, - 0x9c, 0x74, 0x6b, 0xc5, 0xfc, 0x66, 0xbc, 0xb5, 0x28, 0xcf, 0xc8, 0x20, 0x06, 0xab, 0x58, 0x3c, - 0x12, 0xab, 0x78, 0x19, 0x86, 0x9d, 0x56, 0xab, 0x62, 0xf2, 0x99, 0x6c, 0x29, 0x2d, 0xc4, 0xc5, - 0x58, 0xc7, 0xb1, 0x7f, 0xbc, 0x00, 0x63, 0xf2, 0x0b, 0xaa, 0xed, 0xcd, 0x90, 0x44, 0x68, 0x03, - 0x4a, 0x0e, 0x9f, 0x25, 0x22, 0x17, 0xf9, 0x13, 0xd9, 0x72, 0x04, 0x63, 0x4a, 0xe3, 0x0b, 0x7f, - 0x41, 0xd6, 0xc6, 0x31, 0x21, 0xd4, 0x80, 0x49, 0xcf, 0x8f, 0xd8, 0xe1, 0xaf, 0xe0, 0x9d, 0x54, - 0x3b, 0x49, 0xea, 0x67, 0x05, 0xf5, 0xc9, 0xf5, 0x24, 0x15, 0x9c, 0x26, 0x8c, 0x96, 0xa5, 0x6c, - 0xa6, 0x98, 0x2f, 0x0c, 0xd0, 0x27, 0x2e, 0x5b, 0x34, 0x63, 0xff, 0x8a, 0x05, 0x25, 0x89, 0x76, - 0x12, 0x5a, 0xbc, 0x35, 0x18, 0x0c, 0xd9, 0x24, 0xc8, 0xa1, 0xb1, 0x3b, 0x75, 0x9c, 0xcf, 0x57, - 0x7c, 0xa7, 0xf1, 0xff, 0x21, 0x96, 0x34, 0x98, 0x68, 0x5e, 0x75, 0xff, 0x5d, 0x22, 0x9a, 0x57, - 0xfd, 0xc9, 0xb9, 0x94, 0xfe, 0x90, 0xf5, 0x59, 0x93, 0x75, 0x51, 0xd6, 0xab, 0x15, 0x90, 0x2d, - 0xf7, 0x6e, 0x92, 0xf5, 0xaa, 0xb0, 0x52, 0x2c, 0xa0, 0xe8, 0x2d, 0x18, 0xa9, 0x49, 0x99, 0x6c, - 0xbc, 0xc3, 0x2f, 0x76, 0xd4, 0x0f, 0x28, 0x55, 0x12, 0x97, 0x85, 0x2c, 0x69, 0xf5, 0xb1, 0x41, - 0xcd, 0x34, 0x23, 0x28, 0x76, 0x33, 0x23, 0x88, 0xe9, 0xe6, 0x2b, 0xd5, 0x7f, 0xd2, 0x82, 0x01, - 0x2e, 0x8b, 0xeb, 0x4d, 0x14, 0xaa, 0x69, 0xd6, 0xe2, 0xb1, 0xbb, 0x45, 0x0b, 0x85, 0xa6, 0x0c, - 0xad, 0x41, 0x89, 0xfd, 0x60, 0xb2, 0xc4, 0x62, 0xbe, 0x95, 0x3f, 0x6f, 0x55, 0xef, 0xe0, 0x2d, - 0x59, 0x0d, 0xc7, 0x14, 0xec, 0x1f, 0x2b, 0xd2, 0xd3, 0x2d, 0x46, 0x35, 0x2e, 0x7d, 0xeb, 0xe1, - 0x5d, 0xfa, 0x85, 0x87, 0x75, 0xe9, 0x6f, 0xc3, 0x78, 0x4d, 0xd3, 0xc3, 0xc5, 0x33, 0x79, 0xa9, - 0xe3, 0x22, 0xd1, 0x54, 0x76, 0x5c, 0xca, 0xb2, 0x64, 0x12, 0xc1, 0x49, 0xaa, 0xe8, 0xbb, 0x60, - 0x84, 0xcf, 0xb3, 0x68, 0x85, 0x5b, 0x62, 0x3c, 0x95, 0xbf, 0x5e, 0xf4, 0x26, 0xb8, 0x54, 0x4e, - 0xab, 0x8e, 0x0d, 0x62, 0xf6, 0x9f, 0x58, 0x80, 0x96, 0x5b, 0x3b, 0xa4, 0x49, 0x02, 0xa7, 0x11, - 0x8b, 0xd3, 0x7f, 0xd8, 0x82, 0x69, 0x92, 0x2a, 0x5e, 0xf2, 0x9b, 0x4d, 0xf1, 0x68, 0xc9, 0x79, - 0x57, 0x2f, 0xe7, 0xd4, 0x51, 0x6e, 0x10, 0xd3, 0x79, 0x18, 0x38, 0xb7, 0x3d, 0xb4, 0x06, 0x53, - 0xfc, 0x96, 0x54, 0x00, 0xcd, 0xd6, 0xfb, 0x51, 0x41, 0x78, 0x6a, 0x23, 0x8d, 0x82, 0xb3, 0xea, - 0xd9, 0xdf, 0x37, 0x02, 0xb9, 0xbd, 0x78, 0x4f, 0x8f, 0xf0, 0x9e, 0x1e, 0xe1, 0x3d, 0x3d, 0xc2, - 0x7b, 0x7a, 0x84, 0xf7, 0xf4, 0x08, 0xdf, 0xf6, 0x7a, 0x84, 0xbf, 0x60, 0xc1, 0x69, 0x75, 0x0d, - 0x18, 0x0f, 0xdf, 0xcf, 0xc2, 0x14, 0xdf, 0x6e, 0x4b, 0x0d, 0xc7, 0x6d, 0x6e, 0x90, 0x66, 0xab, - 0xe1, 0x44, 0x52, 0xeb, 0x7e, 0x39, 0x73, 0xe5, 0x26, 0x2c, 0x56, 0x8d, 0x8a, 0xdc, 0xf4, 0x3f, - 0x03, 0x80, 0xb3, 0x9a, 0xb1, 0x7f, 0x71, 0x08, 0xfa, 0x97, 0xf7, 0x88, 0x17, 0x9d, 0xc0, 0x13, - 0xa1, 0x06, 0x63, 0xae, 0xb7, 0xe7, 0x37, 0xf6, 0x48, 0x9d, 0xc3, 0x8f, 0xf2, 0x92, 0x3d, 0x23, - 0x48, 0x8f, 0xad, 0x1a, 0x24, 0x70, 0x82, 0xe4, 0xc3, 0x90, 0x26, 0x5f, 0x81, 0x01, 0x7e, 0x88, - 0x0b, 0x51, 0x72, 0xe6, 0x99, 0xcd, 0x06, 0x51, 0x5c, 0x4d, 0xb1, 0xa4, 0x9b, 0x5f, 0x12, 0xa2, - 0x3a, 0xfa, 0x0c, 0x8c, 0x6d, 0xb9, 0x41, 0x18, 0x6d, 0xb8, 0x4d, 0x12, 0x46, 0x4e, 0xb3, 0xf5, - 0x00, 0xd2, 0x63, 0x35, 0x0e, 0x2b, 0x06, 0x25, 0x9c, 0xa0, 0x8c, 0xb6, 0x61, 0xb4, 0xe1, 0xe8, - 0x4d, 0x0d, 0x1e, 0xb9, 0x29, 0x75, 0x3b, 0x5c, 0xd7, 0x09, 0x61, 0x93, 0x2e, 0xdd, 0x4e, 0x35, - 0x26, 0x00, 0x1d, 0x62, 0x62, 0x01, 0xb5, 0x9d, 0xb8, 0xe4, 0x93, 0xc3, 0x28, 0xa3, 0xc3, 0x0c, - 0x64, 0x4b, 0x26, 0xa3, 0xa3, 0x99, 0xc1, 0x7e, 0x1a, 0x4a, 0x84, 0x0e, 0x21, 0x25, 0x2c, 0x2e, - 0x98, 0xf9, 0xde, 0xfa, 0xba, 0xe6, 0xd6, 0x02, 0xdf, 0x94, 0xdb, 0x2f, 0x4b, 0x4a, 0x38, 0x26, - 0x8a, 0x96, 0x60, 0x20, 0x24, 0x81, 0x4b, 0x42, 0x71, 0xd5, 0x74, 0x98, 0x46, 0x86, 0xc6, 0x7d, - 0x4b, 0xf8, 0x6f, 0x2c, 0xaa, 0xd2, 0xe5, 0xe5, 0x30, 0x91, 0x26, 0xbb, 0x0c, 0xb4, 0xe5, 0xb5, - 0xc0, 0x4a, 0xb1, 0x80, 0xa2, 0x37, 0x60, 0x30, 0x20, 0x0d, 0xa6, 0x18, 0x1a, 0xed, 0x7d, 0x91, - 0x73, 0x3d, 0x13, 0xaf, 0x87, 0x25, 0x01, 0x74, 0x0d, 0x50, 0x40, 0x28, 0xa3, 0xe4, 0x7a, 0xdb, - 0xca, 0x6c, 0x54, 0x1c, 0xb4, 0x8a, 0x21, 0xc5, 0x31, 0x86, 0x74, 0x2b, 0xc2, 0x19, 0xd5, 0xd0, - 0x15, 0x98, 0x54, 0xa5, 0xab, 0x5e, 0x18, 0x39, 0xf4, 0x80, 0x1b, 0x67, 0xb4, 0x94, 0x9c, 0x02, - 0x27, 0x11, 0x70, 0xba, 0x8e, 0xfd, 0x25, 0x0b, 0xf8, 0x38, 0x9f, 0xc0, 0xeb, 0xfc, 0x75, 0xf3, - 0x75, 0x7e, 0x36, 0x77, 0xe6, 0x72, 0x5e, 0xe6, 0x5f, 0xb2, 0x60, 0x58, 0x9b, 0xd9, 0x78, 0xcd, - 0x5a, 0x1d, 0xd6, 0x6c, 0x1b, 0x26, 0xe8, 0x4a, 0xbf, 0xb1, 0x19, 0x92, 0x60, 0x8f, 0xd4, 0xd9, - 0xc2, 0x2c, 0x3c, 0xd8, 0xc2, 0x54, 0x26, 0x6a, 0xd7, 0x13, 0x04, 0x71, 0xaa, 0x09, 0xfb, 0xd3, - 0xb2, 0xab, 0xca, 0xa2, 0xaf, 0xa6, 0xe6, 0x3c, 0x61, 0xd1, 0xa7, 0x66, 0x15, 0xc7, 0x38, 0x74, - 0xab, 0xed, 0xf8, 0x61, 0x94, 0xb4, 0xe8, 0xbb, 0xea, 0x87, 0x11, 0x66, 0x10, 0xfb, 0x45, 0x80, - 0xe5, 0xbb, 0xa4, 0xc6, 0x57, 0xac, 0xfe, 0x78, 0xb0, 0xf2, 0x1f, 0x0f, 0xf6, 0x6f, 0x59, 0x30, - 0xb6, 0xb2, 0x64, 0xdc, 0x5c, 0x73, 0x00, 0xfc, 0xc5, 0x73, 0xfb, 0xf6, 0xba, 0x54, 0x87, 0x73, - 0x8d, 0xa6, 0x2a, 0xc5, 0x1a, 0x06, 0x3a, 0x0b, 0xc5, 0x46, 0xdb, 0x13, 0xe2, 0xc3, 0x41, 0x7a, - 0x3d, 0x5e, 0x6f, 0x7b, 0x98, 0x96, 0x69, 0x2e, 0x05, 0xc5, 0x9e, 0x5d, 0x0a, 0xba, 0x86, 0x12, - 0x40, 0xb3, 0xd0, 0x7f, 0xe7, 0x8e, 0x5b, 0xe7, 0x0e, 0x9b, 0x42, 0x55, 0x7f, 0xfb, 0xf6, 0x6a, - 0x39, 0xc4, 0xbc, 0xdc, 0xfe, 0x42, 0x11, 0x66, 0x56, 0x1a, 0xe4, 0xee, 0x3b, 0x74, 0x5a, 0xed, - 0xd5, 0x21, 0xe2, 0x68, 0x82, 0x98, 0xa3, 0x3a, 0xbd, 0x74, 0x1f, 0x8f, 0x2d, 0x18, 0xe4, 0x06, - 0x6d, 0xd2, 0x85, 0xf5, 0xb5, 0xac, 0xd6, 0xf3, 0x07, 0x64, 0x8e, 0x1b, 0xc6, 0x09, 0x8f, 0x38, - 0x75, 0x61, 0x8a, 0x52, 0x2c, 0x89, 0xcf, 0xbc, 0x0a, 0x23, 0x3a, 0xe6, 0x91, 0xdc, 0xcf, 0xfe, - 0x9f, 0x22, 0x4c, 0xd0, 0x1e, 0x3c, 0xd4, 0x89, 0xb8, 0x99, 0x9e, 0x88, 0xe3, 0x76, 0x41, 0xea, - 0x3e, 0x1b, 0x6f, 0x25, 0x67, 0xe3, 0x72, 0xde, 0x6c, 0x9c, 0xf4, 0x1c, 0x7c, 0xaf, 0x05, 0x53, - 0x2b, 0x0d, 0xbf, 0xb6, 0x9b, 0x70, 0x13, 0x7a, 0x19, 0x86, 0xe9, 0x71, 0x1c, 0x1a, 0x1e, 0xf3, - 0x46, 0x0c, 0x05, 0x01, 0xc2, 0x3a, 0x9e, 0x56, 0xed, 0xe6, 0xcd, 0xd5, 0x72, 0x56, 0xe8, 0x05, - 0x01, 0xc2, 0x3a, 0x9e, 0xfd, 0x1b, 0x16, 0x9c, 0xbb, 0xb2, 0xb4, 0x1c, 0x2f, 0xc5, 0x54, 0xf4, - 0x87, 0x8b, 0x30, 0xd0, 0xaa, 0x6b, 0x5d, 0x89, 0xc5, 0xab, 0x65, 0xd6, 0x0b, 0x01, 0x7d, 0xb7, - 0x44, 0x36, 0xb9, 0x09, 0x70, 0x05, 0x57, 0x96, 0xc4, 0xb9, 0x2b, 0xb5, 0x29, 0x56, 0xae, 0x36, - 0xe5, 0x29, 0x18, 0xa4, 0xf7, 0x82, 0x5b, 0x93, 0xfd, 0xe6, 0x0a, 0x5a, 0x5e, 0x84, 0x25, 0xcc, - 0xfe, 0x39, 0x0b, 0xa6, 0xae, 0xb8, 0x11, 0xbd, 0xb4, 0x93, 0xe1, 0x0d, 0xe8, 0xad, 0x1d, 0xba, - 0x91, 0x1f, 0xec, 0x27, 0xc3, 0x1b, 0x60, 0x05, 0xc1, 0x1a, 0x16, 0xff, 0xa0, 0x3d, 0x97, 0x59, - 0x68, 0x17, 0x4c, 0xfd, 0x15, 0x16, 0xe5, 0x58, 0x61, 0xd0, 0xf1, 0xaa, 0xbb, 0x01, 0x13, 0xfd, - 0xed, 0x8b, 0x83, 0x5b, 0x8d, 0x57, 0x59, 0x02, 0x70, 0x8c, 0x63, 0xff, 0x91, 0x05, 0xb3, 0x57, - 0x1a, 0xed, 0x30, 0x22, 0xc1, 0x56, 0x98, 0x73, 0xe8, 0xbe, 0x08, 0x25, 0x22, 0x05, 0xed, 0xa2, - 0xd7, 0x8a, 0x11, 0x55, 0x12, 0x78, 0x1e, 0x65, 0x41, 0xe1, 0xf5, 0xe0, 0xcb, 0x78, 0x34, 0x67, - 0xb4, 0x15, 0x40, 0x44, 0x6f, 0x4b, 0x0f, 0x3b, 0xc1, 0xfc, 0xd7, 0x97, 0x53, 0x50, 0x9c, 0x51, - 0xc3, 0xfe, 0x09, 0x0b, 0x4e, 0xab, 0x0f, 0x7e, 0xd7, 0x7d, 0xa6, 0xfd, 0xd5, 0x02, 0x8c, 0x5e, - 0xdd, 0xd8, 0xa8, 0x5c, 0x21, 0x91, 0xb6, 0x2a, 0x3b, 0xab, 0xcf, 0xb1, 0xa6, 0x05, 0xec, 0xf4, - 0x46, 0x6c, 0x47, 0x6e, 0x63, 0x8e, 0x47, 0x2f, 0x9a, 0x5b, 0xf5, 0xa2, 0x1b, 0x41, 0x35, 0x0a, - 0x5c, 0x6f, 0x3b, 0x73, 0xa5, 0x4b, 0x9e, 0xa5, 0x98, 0xc7, 0xb3, 0xa0, 0x17, 0x61, 0x80, 0x85, - 0x4f, 0x92, 0x93, 0xf0, 0xa8, 0x7a, 0x62, 0xb1, 0xd2, 0xc3, 0x83, 0xd9, 0xd2, 0x4d, 0xbc, 0xca, - 0xff, 0x60, 0x81, 0x8a, 0x6e, 0xc2, 0xf0, 0x4e, 0x14, 0xb5, 0xae, 0x12, 0xa7, 0x4e, 0x02, 0x79, - 0xca, 0x9e, 0xcf, 0x3a, 0x65, 0xe9, 0x20, 0x70, 0xb4, 0xf8, 0x60, 0x8a, 0xcb, 0x42, 0xac, 0xd3, - 0xb1, 0xab, 0x00, 0x31, 0xec, 0x98, 0x14, 0x20, 0xf6, 0x06, 0x94, 0xe8, 0xe7, 0x2e, 0x34, 0x5c, - 0xa7, 0xb3, 0x8a, 0xf9, 0x59, 0x28, 0x49, 0x05, 0x72, 0x28, 0x7c, 0xad, 0xd9, 0x8d, 0x24, 0xf5, - 0xcb, 0x21, 0x8e, 0xe1, 0xf6, 0x16, 0x9c, 0x62, 0xe6, 0x80, 0x4e, 0xb4, 0x63, 0xac, 0xbe, 0xee, - 0xd3, 0xfc, 0x9c, 0x78, 0xb1, 0xf1, 0x3e, 0x4f, 0x6b, 0xee, 0x8c, 0x23, 0x92, 0x62, 0xfc, 0x7a, - 0xb3, 0xbf, 0xd1, 0x07, 0x8f, 0xae, 0x56, 0xf3, 0xc3, 0x7f, 0xbc, 0x02, 0x23, 0x9c, 0x11, 0xa4, - 0x93, 0xee, 0x34, 0x44, 0xbb, 0x4a, 0xb6, 0xb9, 0xa1, 0xc1, 0xb0, 0x81, 0x89, 0xce, 0x41, 0xd1, - 0x7d, 0xdb, 0x4b, 0x3a, 0xfb, 0xac, 0xbe, 0xb9, 0x8e, 0x69, 0x39, 0x05, 0x53, 0x9e, 0x92, 0x1f, - 0xd6, 0x0a, 0xac, 0xf8, 0xca, 0xd7, 0x61, 0xcc, 0x0d, 0x6b, 0xa1, 0xbb, 0xea, 0xd1, 0x1d, 0xa8, - 0xed, 0x61, 0x25, 0x4d, 0xa0, 0x9d, 0x56, 0x50, 0x9c, 0xc0, 0xd6, 0x6e, 0x8e, 0xfe, 0x9e, 0xf9, - 0xd2, 0xae, 0xce, 0xc7, 0xf4, 0x60, 0x6f, 0xb1, 0xaf, 0x0b, 0x99, 0x90, 0x5a, 0x1c, 0xec, 0xfc, - 0x83, 0x43, 0x2c, 0x61, 0xf4, 0xa9, 0x56, 0xdb, 0x71, 0x5a, 0x0b, 0xed, 0x68, 0xa7, 0xec, 0x86, - 0x35, 0x7f, 0x8f, 0x04, 0xfb, 0xec, 0x95, 0x3d, 0x14, 0x3f, 0xd5, 0x14, 0x60, 0xe9, 0xea, 0x42, - 0x85, 0x62, 0xe2, 0x74, 0x1d, 0xb4, 0x00, 0xe3, 0xb2, 0xb0, 0x4a, 0x42, 0x76, 0xb8, 0x0f, 0x33, - 0x32, 0xca, 0xfd, 0x46, 0x14, 0x2b, 0x22, 0x49, 0x7c, 0x93, 0x75, 0x85, 0xe3, 0x60, 0x5d, 0x3f, - 0x04, 0xa3, 0xae, 0xe7, 0x46, 0xae, 0x13, 0xf9, 0x5c, 0xc3, 0xc2, 0x1f, 0xd4, 0x4c, 0x74, 0xbc, - 0xaa, 0x03, 0xb0, 0x89, 0x67, 0xff, 0xfb, 0x3e, 0x98, 0x64, 0xd3, 0xf6, 0xde, 0x0a, 0xfb, 0x76, - 0x5a, 0x61, 0x37, 0xd3, 0x2b, 0xec, 0x38, 0x78, 0xf2, 0x07, 0x5e, 0x66, 0x9f, 0x81, 0x92, 0xf2, - 0x38, 0x92, 0x2e, 0x87, 0x56, 0x8e, 0xcb, 0x61, 0xf7, 0x7b, 0x59, 0x1a, 0x6d, 0x15, 0x33, 0x8d, - 0xb6, 0xbe, 0x6c, 0x41, 0xac, 0x32, 0x40, 0x6f, 0x42, 0xa9, 0xe5, 0x33, 0x5b, 0xc4, 0x40, 0x1a, - 0xf8, 0x3e, 0xd9, 0x51, 0xe7, 0xc0, 0x23, 0x20, 0x05, 0x7c, 0x14, 0x2a, 0xb2, 0x2a, 0x8e, 0xa9, - 0xa0, 0x6b, 0x30, 0xd8, 0x0a, 0x48, 0x35, 0x62, 0xe1, 0x39, 0x7a, 0x27, 0xc8, 0x57, 0x0d, 0xaf, - 0x88, 0x25, 0x05, 0xfb, 0x3f, 0x5a, 0x30, 0x91, 0x44, 0x45, 0x1f, 0x86, 0x3e, 0x72, 0x97, 0xd4, - 0x44, 0x7f, 0x33, 0x2f, 0xd9, 0x58, 0xe8, 0xc0, 0x07, 0x80, 0xfe, 0xc7, 0xac, 0x16, 0xba, 0x0a, - 0x83, 0xf4, 0x86, 0xbd, 0xa2, 0x42, 0x51, 0x3d, 0x9e, 0x77, 0x4b, 0x2b, 0x56, 0x85, 0x77, 0x4e, - 0x14, 0x61, 0x59, 0x9d, 0x59, 0x4a, 0xd5, 0x5a, 0x55, 0xfa, 0x78, 0x89, 0x3a, 0xbd, 0xb1, 0x37, - 0x96, 0x2a, 0x1c, 0x49, 0x50, 0xe3, 0x96, 0x52, 0xb2, 0x10, 0xc7, 0x44, 0xec, 0x9f, 0xb7, 0x00, - 0xb8, 0x61, 0x98, 0xe3, 0x6d, 0x93, 0x13, 0x90, 0x93, 0x97, 0xa1, 0x2f, 0x6c, 0x91, 0x5a, 0x27, - 0x33, 0xd9, 0xb8, 0x3f, 0xd5, 0x16, 0xa9, 0xc5, 0x2b, 0x8e, 0xfe, 0xc3, 0xac, 0xb6, 0xfd, 0xfd, - 0x00, 0x63, 0x31, 0xda, 0x6a, 0x44, 0x9a, 0xe8, 0x79, 0x23, 0x4c, 0xc1, 0xd9, 0x44, 0x98, 0x82, - 0x12, 0xc3, 0xd6, 0x44, 0xb2, 0x9f, 0x81, 0x62, 0xd3, 0xb9, 0x2b, 0x64, 0x6e, 0xcf, 0x76, 0xee, - 0x06, 0xa5, 0x3f, 0xb7, 0xe6, 0xdc, 0xe5, 0xcf, 0xd2, 0x67, 0xe5, 0x0e, 0x59, 0x73, 0xee, 0x1e, - 0x72, 0x63, 0x58, 0x76, 0x4a, 0x5f, 0x77, 0xc3, 0xe8, 0x73, 0xff, 0x2e, 0xfe, 0xcf, 0xf6, 0x1d, - 0x6d, 0x84, 0xb5, 0xe5, 0x7a, 0xc2, 0xe6, 0xa9, 0xa7, 0xb6, 0x5c, 0x2f, 0xd9, 0x96, 0xeb, 0xf5, - 0xd0, 0x96, 0xeb, 0xa1, 0x7b, 0x30, 0x28, 0x4c, 0x12, 0x45, 0x58, 0xa0, 0xf9, 0x1e, 0xda, 0x13, - 0x16, 0x8d, 0xbc, 0xcd, 0x79, 0xf9, 0xec, 0x16, 0xa5, 0x5d, 0xdb, 0x95, 0x0d, 0xa2, 0xbf, 0x68, - 0xc1, 0x98, 0xf8, 0x8d, 0xc9, 0xdb, 0x6d, 0x12, 0x46, 0x82, 0x2d, 0xfd, 0x60, 0xef, 0x7d, 0x10, - 0x15, 0x79, 0x57, 0x3e, 0x28, 0xef, 0x19, 0x13, 0xd8, 0xb5, 0x47, 0x89, 0x5e, 0xa0, 0xbf, 0x65, - 0xc1, 0xa9, 0xa6, 0x73, 0x97, 0xb7, 0xc8, 0xcb, 0xb0, 0x13, 0xb9, 0xbe, 0x50, 0xed, 0x7f, 0xb8, - 0xb7, 0xe9, 0x4f, 0x55, 0xe7, 0x9d, 0x94, 0xfa, 0xc7, 0x53, 0x59, 0x28, 0x5d, 0xbb, 0x9a, 0xd9, - 0xaf, 0x99, 0x2d, 0x18, 0x92, 0xeb, 0x2d, 0x43, 0xb8, 0x51, 0xd6, 0x79, 0xee, 0x23, 0x5b, 0x84, - 0xea, 0xee, 0xff, 0xb4, 0x1d, 0xb1, 0xd6, 0x1e, 0x6a, 0x3b, 0x9f, 0x81, 0x11, 0x7d, 0x8d, 0x3d, - 0xd4, 0xb6, 0xde, 0x86, 0xa9, 0x8c, 0xb5, 0xf4, 0x50, 0x9b, 0xbc, 0x03, 0x67, 0x73, 0xd7, 0xc7, - 0xc3, 0x6c, 0xd8, 0xfe, 0xaa, 0xa5, 0x9f, 0x83, 0x27, 0xa0, 0xac, 0x58, 0x32, 0x95, 0x15, 0xe7, - 0x3b, 0xef, 0x9c, 0x1c, 0x8d, 0xc5, 0x5b, 0x7a, 0xa7, 0xe9, 0xa9, 0x8e, 0xde, 0x80, 0x81, 0x06, - 0x2d, 0x91, 0x86, 0xad, 0x76, 0xf7, 0x1d, 0x19, 0x33, 0x93, 0xac, 0x3c, 0xc4, 0x82, 0x82, 0xfd, - 0x4b, 0x16, 0xf4, 0x9d, 0xc0, 0x48, 0x60, 0x73, 0x24, 0x9e, 0xcf, 0x25, 0x2d, 0x22, 0x24, 0xcf, - 0x61, 0xe7, 0xce, 0xf2, 0xdd, 0x88, 0x78, 0x21, 0xbb, 0x91, 0x33, 0x07, 0xe6, 0xa7, 0x2d, 0x98, - 0xba, 0xee, 0x3b, 0xf5, 0x45, 0xa7, 0xe1, 0x78, 0x35, 0x12, 0xac, 0x7a, 0xdb, 0x47, 0xb2, 0xca, - 0x2e, 0x74, 0xb5, 0xca, 0x5e, 0x92, 0x46, 0x4d, 0x7d, 0xf9, 0xf3, 0x47, 0x39, 0xe9, 0x64, 0xe0, - 0x16, 0xc3, 0xfc, 0x76, 0x07, 0x90, 0xde, 0x4b, 0xe1, 0x23, 0x83, 0x61, 0xd0, 0xe5, 0xfd, 0x15, - 0x93, 0xf8, 0x74, 0x36, 0x87, 0x9b, 0xfa, 0x3c, 0xcd, 0xfb, 0x83, 0x17, 0x60, 0x49, 0xc8, 0x7e, - 0x05, 0x32, 0x1d, 0xed, 0xbb, 0xcb, 0x25, 0xec, 0x8f, 0xc3, 0x24, 0xab, 0x79, 0x44, 0xc9, 0x80, - 0x9d, 0x90, 0xa6, 0x66, 0x84, 0xe0, 0xb3, 0x3f, 0x6f, 0xc1, 0xf8, 0x7a, 0x22, 0x32, 0xd9, 0x45, - 0xa6, 0x7f, 0xcd, 0x10, 0xe2, 0x57, 0x59, 0x29, 0x16, 0xd0, 0x63, 0x17, 0x72, 0xfd, 0xb9, 0x05, - 0x71, 0xec, 0x8b, 0x13, 0x60, 0xdf, 0x96, 0x0c, 0xf6, 0x2d, 0x93, 0x91, 0x55, 0xdd, 0xc9, 0xe3, - 0xde, 0xd0, 0x35, 0x15, 0x15, 0xaa, 0x03, 0x0f, 0x1b, 0x93, 0xe1, 0x4b, 0x71, 0xcc, 0x0c, 0x1d, - 0x25, 0xe3, 0x44, 0xd9, 0xbf, 0x5d, 0x00, 0xa4, 0x70, 0x7b, 0x8e, 0x5a, 0x95, 0xae, 0x71, 0x3c, - 0x51, 0xab, 0xf6, 0x00, 0x31, 0x0b, 0x82, 0xc0, 0xf1, 0x42, 0x4e, 0xd6, 0x15, 0x62, 0xbd, 0xa3, - 0x99, 0x27, 0xcc, 0x88, 0x26, 0xd1, 0xf5, 0x14, 0x35, 0x9c, 0xd1, 0x82, 0x66, 0x19, 0xd2, 0xdf, - 0xab, 0x65, 0xc8, 0x40, 0x17, 0x3f, 0xb8, 0xaf, 0x58, 0x30, 0xaa, 0x86, 0xe9, 0x5d, 0x62, 0xa5, - 0xae, 0xfa, 0x93, 0x73, 0x80, 0x56, 0xb4, 0x2e, 0xb3, 0x8b, 0xe5, 0x3b, 0x99, 0x3f, 0xa3, 0xd3, - 0x70, 0xef, 0x11, 0x15, 0x33, 0x70, 0x56, 0xf8, 0x27, 0x8a, 0xd2, 0xc3, 0x83, 0xd9, 0x51, 0xf5, - 0x8f, 0xc7, 0x44, 0x8e, 0xab, 0xd0, 0x23, 0x79, 0x3c, 0xb1, 0x14, 0xd1, 0xcb, 0xd0, 0xdf, 0xda, - 0x71, 0x42, 0x92, 0xf0, 0xe6, 0xe9, 0xaf, 0xd0, 0xc2, 0xc3, 0x83, 0xd9, 0x31, 0x55, 0x81, 0x95, - 0x60, 0x8e, 0xdd, 0x7b, 0x2c, 0xb0, 0xf4, 0xe2, 0xec, 0x1a, 0x0b, 0xec, 0x4f, 0x2c, 0xe8, 0x5b, - 0xf7, 0xeb, 0x27, 0x71, 0x04, 0xbc, 0x6e, 0x1c, 0x01, 0x8f, 0xe5, 0x85, 0xab, 0xcf, 0xdd, 0xfd, - 0x2b, 0x89, 0xdd, 0x7f, 0x3e, 0x97, 0x42, 0xe7, 0x8d, 0xdf, 0x84, 0x61, 0x16, 0x04, 0x5f, 0x78, - 0x2e, 0xbd, 0x68, 0x6c, 0xf8, 0xd9, 0xc4, 0x86, 0x1f, 0xd7, 0x50, 0xb5, 0x9d, 0xfe, 0x0c, 0x0c, - 0x0a, 0x57, 0x98, 0xa4, 0x5b, 0xa8, 0xc0, 0xc5, 0x12, 0x6e, 0xff, 0x64, 0x11, 0x8c, 0xa0, 0xfb, - 0xe8, 0x57, 0x2c, 0x98, 0x0b, 0xb8, 0x89, 0x6c, 0xbd, 0xdc, 0x0e, 0x5c, 0x6f, 0xbb, 0x5a, 0xdb, - 0x21, 0xf5, 0x76, 0xc3, 0xf5, 0xb6, 0x57, 0xb7, 0x3d, 0x5f, 0x15, 0x2f, 0xdf, 0x25, 0xb5, 0x36, - 0x53, 0xbb, 0x75, 0x89, 0xf0, 0xaf, 0x4c, 0xcd, 0x5f, 0xb8, 0x7f, 0x30, 0x3b, 0x87, 0x8f, 0x44, - 0x1b, 0x1f, 0xb1, 0x2f, 0xe8, 0x37, 0x2c, 0x98, 0xe7, 0xb1, 0xe8, 0x7b, 0xef, 0x7f, 0x87, 0xd7, - 0x72, 0x45, 0x92, 0x8a, 0x89, 0x6c, 0x90, 0xa0, 0xb9, 0xf8, 0x21, 0x31, 0xa0, 0xf3, 0x95, 0xa3, - 0xb5, 0x85, 0x8f, 0xda, 0x39, 0xfb, 0x1f, 0x16, 0x61, 0x54, 0xc4, 0x8c, 0x12, 0x77, 0xc0, 0xcb, - 0xc6, 0x92, 0x78, 0x3c, 0xb1, 0x24, 0x26, 0x0d, 0xe4, 0xe3, 0x39, 0xfe, 0x43, 0x98, 0xa4, 0x87, - 0xf3, 0x55, 0xe2, 0x04, 0xd1, 0x26, 0x71, 0xb8, 0xc1, 0x57, 0xf1, 0xc8, 0xa7, 0xbf, 0x92, 0x4f, - 0x5e, 0x4f, 0x12, 0xc3, 0x69, 0xfa, 0xdf, 0x4e, 0x77, 0x8e, 0x07, 0x13, 0xa9, 0xb0, 0x5f, 0x9f, - 0x80, 0x92, 0xf2, 0xe3, 0x10, 0x87, 0x4e, 0xe7, 0xe8, 0x79, 0x49, 0x0a, 0x5c, 0xfc, 0x15, 0xfb, - 0x10, 0xc5, 0xe4, 0xec, 0xbf, 0x5d, 0x30, 0x1a, 0xe4, 0x93, 0xb8, 0x0e, 0x43, 0x4e, 0x18, 0xba, - 0xdb, 0x1e, 0xa9, 0x77, 0x92, 0x50, 0xa6, 0x9a, 0x61, 0xbe, 0x34, 0x0b, 0xa2, 0x26, 0x56, 0x34, - 0xd0, 0x55, 0x6e, 0x56, 0xb7, 0x47, 0x3a, 0x89, 0x27, 0x53, 0xd4, 0x40, 0x1a, 0xde, 0xed, 0x11, - 0x2c, 0xea, 0xa3, 0x4f, 0x72, 0xbb, 0xc7, 0x6b, 0x9e, 0x7f, 0xc7, 0xbb, 0xe2, 0xfb, 0x32, 0x2e, - 0x43, 0x6f, 0x04, 0x27, 0xa5, 0xb5, 0xa3, 0xaa, 0x8e, 0x4d, 0x6a, 0xbd, 0xc5, 0xd1, 0xfc, 0x2c, - 0xb0, 0xd8, 0xdb, 0xa6, 0xdb, 0x74, 0x88, 0x08, 0x8c, 0x8b, 0x80, 0x64, 0xb2, 0x4c, 0x8c, 0x5d, - 0xe6, 0x53, 0xce, 0xac, 0x1d, 0x0b, 0xd2, 0xaf, 0x99, 0x24, 0x70, 0x92, 0xa6, 0xfd, 0xb3, 0x16, - 0x30, 0x17, 0xd2, 0x13, 0xe0, 0x47, 0x3e, 0x62, 0xf2, 0x23, 0xd3, 0x79, 0x83, 0x9c, 0xc3, 0x8a, - 0xbc, 0xc4, 0x57, 0x56, 0x25, 0xf0, 0xef, 0xee, 0x0b, 0x63, 0x95, 0xee, 0xef, 0x0f, 0xfb, 0x7f, - 0x5a, 0xfc, 0x10, 0x53, 0x5e, 0x16, 0xe8, 0xbb, 0x61, 0xa8, 0xe6, 0xb4, 0x9c, 0x1a, 0xcf, 0x10, - 0x93, 0x2b, 0xd1, 0x33, 0x2a, 0xcd, 0x2d, 0x89, 0x1a, 0x5c, 0x42, 0x25, 0x03, 0xdb, 0x0d, 0xc9, - 0xe2, 0xae, 0x52, 0x29, 0xd5, 0xe4, 0xcc, 0x2e, 0x8c, 0x1a, 0xc4, 0x1e, 0xaa, 0x38, 0xe3, 0xbb, - 0xf9, 0x15, 0xab, 0x02, 0x31, 0x36, 0x61, 0xd2, 0xd3, 0xfe, 0xd3, 0x0b, 0x45, 0x3e, 0x2e, 0x9f, - 0xec, 0x76, 0x89, 0xb2, 0xdb, 0x47, 0xf3, 0x4e, 0x4d, 0x90, 0xc1, 0x69, 0xca, 0xf6, 0x4f, 0x59, - 0xf0, 0x88, 0x8e, 0xa8, 0x39, 0xc0, 0x74, 0x53, 0x92, 0x94, 0x61, 0xc8, 0x6f, 0x91, 0xc0, 0x89, - 0xfc, 0x40, 0xdc, 0x1a, 0x97, 0xe4, 0xa0, 0xdf, 0x10, 0xe5, 0x87, 0x22, 0xde, 0xb9, 0xa4, 0x2e, - 0xcb, 0xb1, 0xaa, 0x49, 0x5f, 0x9f, 0x6c, 0x30, 0x42, 0xe1, 0xea, 0xc4, 0xce, 0x00, 0xa6, 0x49, - 0x0f, 0xb1, 0x80, 0xd8, 0xdf, 0xb0, 0xf8, 0xc2, 0xd2, 0xbb, 0x8e, 0xde, 0x86, 0x89, 0xa6, 0x13, - 0xd5, 0x76, 0x96, 0xef, 0xb6, 0x02, 0xae, 0x72, 0x92, 0xe3, 0xf4, 0x6c, 0xb7, 0x71, 0xd2, 0x3e, - 0x32, 0x36, 0xe5, 0x5c, 0x4b, 0x10, 0xc3, 0x29, 0xf2, 0x68, 0x13, 0x86, 0x59, 0x19, 0xf3, 0xe2, - 0x0b, 0x3b, 0xb1, 0x06, 0x79, 0xad, 0x29, 0x63, 0x84, 0xb5, 0x98, 0x0e, 0xd6, 0x89, 0xda, 0x5f, - 0x2e, 0xf2, 0xdd, 0xce, 0x58, 0xf9, 0x67, 0x60, 0xb0, 0xe5, 0xd7, 0x97, 0x56, 0xcb, 0x58, 0xcc, - 0x82, 0xba, 0x46, 0x2a, 0xbc, 0x18, 0x4b, 0x38, 0xba, 0x04, 0x43, 0xe2, 0xa7, 0x54, 0x11, 0xb2, - 0xb3, 0x59, 0xe0, 0x85, 0x58, 0x41, 0xd1, 0x0b, 0x00, 0xad, 0xc0, 0xdf, 0x73, 0xeb, 0x2c, 0xba, - 0x44, 0xd1, 0xb4, 0x23, 0xaa, 0x28, 0x08, 0xd6, 0xb0, 0xd0, 0x6b, 0x30, 0xda, 0xf6, 0x42, 0xce, - 0x8e, 0x68, 0xb1, 0x64, 0x95, 0x85, 0xcb, 0x4d, 0x1d, 0x88, 0x4d, 0x5c, 0xb4, 0x00, 0x03, 0x91, - 0xc3, 0xec, 0x62, 0xfa, 0xf3, 0xcd, 0x7d, 0x37, 0x28, 0x86, 0x9e, 0x8c, 0x84, 0x56, 0xc0, 0xa2, - 0x22, 0xfa, 0x84, 0x74, 0xa8, 0xe5, 0x07, 0xbb, 0xb0, 0xb3, 0xef, 0xed, 0x12, 0xd0, 0xdc, 0x69, - 0x85, 0xfd, 0xbe, 0x41, 0x0b, 0xbd, 0x0a, 0x40, 0xee, 0x46, 0x24, 0xf0, 0x9c, 0x86, 0xb2, 0x66, - 0x53, 0x7c, 0x41, 0xd9, 0x5f, 0xf7, 0xa3, 0x9b, 0x21, 0x59, 0x56, 0x18, 0x58, 0xc3, 0xb6, 0x7f, - 0xa3, 0x04, 0x10, 0xf3, 0xed, 0xe8, 0x5e, 0xea, 0xe0, 0x7a, 0xae, 0x33, 0xa7, 0x7f, 0x7c, 0xa7, - 0x16, 0xfa, 0x01, 0x0b, 0x86, 0x9d, 0x46, 0xc3, 0xaf, 0x39, 0x3c, 0xda, 0x6f, 0xa1, 0xf3, 0xc1, - 0x29, 0xda, 0x5f, 0x88, 0x6b, 0xf0, 0x2e, 0xbc, 0x28, 0x57, 0xa8, 0x06, 0xe9, 0xda, 0x0b, 0xbd, - 0x61, 0xf4, 0x01, 0xf9, 0x54, 0x2c, 0x1a, 0x43, 0xa9, 0x9e, 0x8a, 0x25, 0x76, 0x47, 0xe8, 0xaf, - 0xc4, 0x9b, 0xc6, 0x2b, 0xb1, 0x2f, 0xdf, 0x63, 0xd0, 0x60, 0x5f, 0xbb, 0x3d, 0x10, 0x51, 0x45, - 0x8f, 0x1e, 0xd0, 0x9f, 0xef, 0x9e, 0xa7, 0xbd, 0x93, 0xba, 0x44, 0x0e, 0xf8, 0x0c, 0x8c, 0xd7, - 0x4d, 0x26, 0x40, 0xac, 0xc4, 0xa7, 0xf3, 0xe8, 0x26, 0x78, 0x86, 0xf8, 0xda, 0x4f, 0x00, 0x70, - 0x92, 0x30, 0xaa, 0xf0, 0x60, 0x12, 0xab, 0xde, 0x96, 0x2f, 0x7c, 0x3d, 0xec, 0xdc, 0xb9, 0xdc, - 0x0f, 0x23, 0xd2, 0xa4, 0x98, 0xf1, 0xed, 0xbe, 0x2e, 0xea, 0x62, 0x45, 0x05, 0xbd, 0x01, 0x03, - 0xcc, 0x3f, 0x2b, 0x9c, 0x1e, 0xca, 0x97, 0x38, 0x9b, 0xd1, 0xd1, 0xe2, 0x0d, 0xc9, 0xfe, 0x86, - 0x58, 0x50, 0x40, 0x57, 0xa5, 0xf7, 0x63, 0xb8, 0xea, 0xdd, 0x0c, 0x09, 0xf3, 0x7e, 0x2c, 0x2d, - 0x3e, 0x19, 0x3b, 0x36, 0xf2, 0xf2, 0xcc, 0x94, 0x65, 0x46, 0x4d, 0xca, 0x45, 0x89, 0xff, 0x32, - 0x13, 0xda, 0x34, 0xe4, 0x77, 0xcf, 0xcc, 0x96, 0x16, 0x0f, 0xe7, 0x2d, 0x93, 0x04, 0x4e, 0xd2, - 0xa4, 0x1c, 0x29, 0xdf, 0xf5, 0xc2, 0x5b, 0xa4, 0xdb, 0xd9, 0xc1, 0x1f, 0xe2, 0xec, 0x36, 0xe2, - 0x25, 0x58, 0xd4, 0x3f, 0x51, 0xf6, 0x60, 0xc6, 0x83, 0x89, 0xe4, 0x16, 0x7d, 0xa8, 0xec, 0xc8, - 0x1f, 0xf4, 0xc1, 0x98, 0xb9, 0xa4, 0xd0, 0x3c, 0x94, 0x04, 0x11, 0x95, 0x4d, 0x40, 0xed, 0x92, - 0x35, 0x09, 0xc0, 0x31, 0x0e, 0x4b, 0x22, 0xc1, 0xaa, 0x6b, 0xe6, 0xc1, 0x71, 0x12, 0x09, 0x05, - 0xc1, 0x1a, 0x16, 0x7d, 0x58, 0x6d, 0xfa, 0x7e, 0xa4, 0x2e, 0x24, 0xb5, 0xee, 0x16, 0x59, 0x29, - 0x16, 0x50, 0x7a, 0x11, 0xed, 0x92, 0xc0, 0x23, 0x0d, 0x33, 0xee, 0xb0, 0xba, 0x88, 0xae, 0xe9, - 0x40, 0x6c, 0xe2, 0xd2, 0xeb, 0xd4, 0x0f, 0xd9, 0x42, 0x16, 0xcf, 0xb7, 0xd8, 0xdc, 0xba, 0xca, - 0x1d, 0xb0, 0x25, 0x1c, 0x7d, 0x1c, 0x1e, 0x51, 0xb1, 0x95, 0x30, 0xd7, 0x66, 0xc8, 0x16, 0x07, - 0x0c, 0x69, 0xcb, 0x23, 0x4b, 0xd9, 0x68, 0x38, 0xaf, 0x3e, 0x7a, 0x1d, 0xc6, 0x04, 0x8b, 0x2f, - 0x29, 0x0e, 0x9a, 0x16, 0x46, 0xd7, 0x0c, 0x28, 0x4e, 0x60, 0xcb, 0xc8, 0xc9, 0x8c, 0xcb, 0x96, - 0x14, 0x86, 0xd2, 0x91, 0x93, 0x75, 0x38, 0x4e, 0xd5, 0x40, 0x0b, 0x30, 0xce, 0x79, 0x30, 0xd7, - 0xdb, 0xe6, 0x73, 0x22, 0x9c, 0xb9, 0xd4, 0x96, 0xba, 0x61, 0x82, 0x71, 0x12, 0x1f, 0xbd, 0x02, - 0x23, 0x4e, 0x50, 0xdb, 0x71, 0x23, 0x52, 0x8b, 0xda, 0x01, 0xf7, 0xf2, 0xd2, 0x4c, 0xb4, 0x16, - 0x34, 0x18, 0x36, 0x30, 0xed, 0x7b, 0x30, 0x95, 0x11, 0x99, 0x81, 0x2e, 0x1c, 0xa7, 0xe5, 0xca, - 0x6f, 0x4a, 0x58, 0x38, 0x2f, 0x54, 0x56, 0xe5, 0xd7, 0x68, 0x58, 0x74, 0x75, 0xb2, 0x08, 0x0e, - 0x5a, 0xe2, 0x43, 0xb5, 0x3a, 0x57, 0x24, 0x00, 0xc7, 0x38, 0xf6, 0x7f, 0x29, 0xc0, 0x78, 0x86, - 0x6e, 0x85, 0x25, 0xdf, 0x4b, 0x3c, 0x52, 0xe2, 0x5c, 0x7b, 0x66, 0x20, 0xee, 0xc2, 0x11, 0x02, - 0x71, 0x17, 0xbb, 0x05, 0xe2, 0xee, 0x7b, 0x27, 0x81, 0xb8, 0xcd, 0x11, 0xeb, 0xef, 0x69, 0xc4, - 0x32, 0x82, 0x77, 0x0f, 0x1c, 0x31, 0x78, 0xb7, 0x31, 0xe8, 0x83, 0x3d, 0x0c, 0xfa, 0x8f, 0x15, - 0x60, 0x22, 0x69, 0x4a, 0x7a, 0x02, 0x72, 0xdb, 0x37, 0x0c, 0xb9, 0xed, 0xa5, 0x5e, 0x9c, 0x6f, - 0x73, 0x65, 0xb8, 0x38, 0x21, 0xc3, 0x7d, 0x7f, 0x4f, 0xd4, 0x3a, 0xcb, 0x73, 0xff, 0x6a, 0x01, - 0x4e, 0x67, 0x7a, 0xff, 0x9e, 0xc0, 0xd8, 0xdc, 0x30, 0xc6, 0xe6, 0xf9, 0x9e, 0x1d, 0x93, 0x73, - 0x07, 0xe8, 0x76, 0x62, 0x80, 0xe6, 0x7b, 0x27, 0xd9, 0x79, 0x94, 0xbe, 0x5e, 0x84, 0xf3, 0x99, - 0xf5, 0x62, 0xb1, 0xe7, 0x8a, 0x21, 0xf6, 0x7c, 0x21, 0x21, 0xf6, 0xb4, 0x3b, 0xd7, 0x3e, 0x1e, - 0x39, 0xa8, 0x70, 0xd0, 0x65, 0x61, 0x06, 0x1e, 0x50, 0x06, 0x6a, 0x38, 0xe8, 0x2a, 0x42, 0xd8, - 0xa4, 0xfb, 0xed, 0x24, 0xfb, 0xfc, 0x17, 0x16, 0x9c, 0xcd, 0x9c, 0x9b, 0x13, 0x90, 0x75, 0xad, - 0x9b, 0xb2, 0xae, 0x67, 0x7a, 0x5e, 0xad, 0x39, 0xc2, 0xaf, 0x9f, 0xe9, 0xcf, 0xf9, 0x16, 0xf6, - 0x92, 0xbf, 0x01, 0xc3, 0x4e, 0xad, 0x46, 0xc2, 0x70, 0xcd, 0xaf, 0xab, 0x58, 0xc3, 0xcf, 0xb3, - 0x77, 0x56, 0x5c, 0x7c, 0x78, 0x30, 0x3b, 0x93, 0x24, 0x11, 0x83, 0xb1, 0x4e, 0x01, 0x7d, 0x12, - 0x86, 0x42, 0x71, 0x6f, 0x8a, 0xb9, 0x7f, 0xb1, 0xc7, 0xc1, 0x71, 0x36, 0x49, 0xc3, 0x0c, 0x86, - 0xa4, 0x24, 0x15, 0x8a, 0xa4, 0x19, 0x38, 0xa5, 0x70, 0xac, 0x81, 0x53, 0x5e, 0x00, 0xd8, 0x53, - 0x8f, 0x81, 0xa4, 0xfc, 0x41, 0x7b, 0x26, 0x68, 0x58, 0xe8, 0xa3, 0x30, 0x11, 0xf2, 0x68, 0x81, - 0x4b, 0x0d, 0x27, 0x64, 0x7e, 0x34, 0x62, 0x15, 0xb2, 0x80, 0x4b, 0xd5, 0x04, 0x0c, 0xa7, 0xb0, - 0xd1, 0x8a, 0x6c, 0x95, 0x85, 0x36, 0xe4, 0x0b, 0xf3, 0x62, 0xdc, 0xa2, 0x48, 0xfd, 0x7b, 0x2a, - 0x39, 0xfc, 0x6c, 0xe0, 0xb5, 0x9a, 0xe8, 0x93, 0x00, 0x74, 0xf9, 0x08, 0x39, 0xc4, 0x60, 0xfe, - 0xe1, 0x49, 0x4f, 0x95, 0x7a, 0xa6, 0x71, 0x33, 0xf3, 0xa9, 0x2d, 0x2b, 0x22, 0x58, 0x23, 0x88, - 0x1c, 0x18, 0x8d, 0xff, 0xc5, 0x99, 0x31, 0x2f, 0xe5, 0xb6, 0x90, 0x24, 0xce, 0x44, 0xde, 0x65, - 0x9d, 0x04, 0x36, 0x29, 0xda, 0x3f, 0x31, 0x08, 0x8f, 0x76, 0x38, 0x86, 0xd1, 0x82, 0xa9, 0xea, - 0x7d, 0x36, 0xf9, 0x7e, 0x9f, 0xc9, 0xac, 0x6c, 0x3c, 0xe8, 0x13, 0xab, 0xbd, 0xf0, 0x8e, 0x57, - 0xfb, 0x8f, 0x58, 0x9a, 0x64, 0x85, 0x1b, 0x95, 0x7e, 0xe4, 0x88, 0xd7, 0xcb, 0x31, 0x8a, 0x5a, - 0xb6, 0x32, 0xe4, 0x15, 0x2f, 0xf4, 0xdc, 0x9d, 0xde, 0x05, 0x18, 0x5f, 0xb5, 0x00, 0x09, 0xc9, - 0x0a, 0xa9, 0xab, 0xbd, 0x24, 0x44, 0x19, 0x57, 0x8e, 0xfa, 0xfd, 0x0b, 0x29, 0x4a, 0x7c, 0x24, - 0x5e, 0x95, 0xf7, 0x40, 0x1a, 0xa1, 0xeb, 0x98, 0x64, 0x74, 0x0f, 0x7d, 0x9c, 0x05, 0xd2, 0x75, - 0xef, 0x09, 0xe6, 0x47, 0xec, 0xb5, 0x97, 0x45, 0x10, 0x5d, 0x55, 0x4e, 0xb9, 0xdc, 0xcc, 0xee, - 0xea, 0x48, 0xd8, 0x20, 0x75, 0xb2, 0x4f, 0xef, 0x36, 0x3c, 0x92, 0x33, 0x64, 0x0f, 0xf5, 0x05, - 0xfe, 0x5b, 0x16, 0x9c, 0xeb, 0x18, 0x11, 0xe6, 0x5b, 0x90, 0x37, 0xb4, 0x3f, 0x67, 0x41, 0xf6, - 0x64, 0x1b, 0x16, 0x65, 0xf3, 0x50, 0xaa, 0xd1, 0x42, 0xcd, 0x05, 0x38, 0x8e, 0x8d, 0x20, 0x01, - 0x38, 0xc6, 0x31, 0x0c, 0xc7, 0x0a, 0x5d, 0x0d, 0xc7, 0x7e, 0xd5, 0x82, 0xd4, 0xf9, 0x7e, 0x02, - 0x8c, 0xc6, 0xaa, 0xc9, 0x68, 0x3c, 0xd9, 0xcb, 0x68, 0xe6, 0xf0, 0x18, 0x7f, 0x3c, 0x0e, 0x67, - 0x72, 0x3c, 0xf2, 0xf6, 0x60, 0x72, 0xbb, 0x46, 0x4c, 0xe7, 0xea, 0x4e, 0x41, 0x87, 0x3a, 0x7a, - 0x62, 0xb3, 0xbc, 0xb0, 0x93, 0x29, 0x14, 0x9c, 0x6e, 0x02, 0x7d, 0xce, 0x82, 0x53, 0xce, 0x9d, - 0x70, 0x99, 0x32, 0x8c, 0x6e, 0x6d, 0xb1, 0xe1, 0xd7, 0x76, 0xe9, 0x6d, 0x2c, 0x37, 0xc2, 0x4b, - 0x99, 0x42, 0xbc, 0xdb, 0xd5, 0x14, 0xbe, 0xd1, 0x3c, 0x4b, 0x94, 0x9b, 0x85, 0x85, 0x33, 0xdb, - 0x42, 0x58, 0x64, 0x4f, 0xa0, 0xcf, 0xd1, 0x0e, 0xee, 0xff, 0x59, 0xae, 0x93, 0x9c, 0x03, 0x92, - 0x10, 0xac, 0xe8, 0xa0, 0x4f, 0x43, 0x69, 0x5b, 0x7a, 0xfa, 0x66, 0x70, 0x58, 0xf1, 0x40, 0x76, - 0xf6, 0x7f, 0xe6, 0x9a, 0x78, 0x85, 0x84, 0x63, 0xa2, 0xe8, 0x75, 0x28, 0x7a, 0x5b, 0x61, 0xa7, - 0x5c, 0xb3, 0x09, 0x93, 0x4b, 0x1e, 0x64, 0x63, 0x7d, 0xa5, 0x8a, 0x69, 0x45, 0x74, 0x15, 0x8a, - 0xc1, 0x66, 0x5d, 0x48, 0xa0, 0x33, 0x37, 0x29, 0x5e, 0x2c, 0xe7, 0xf4, 0x8a, 0x51, 0xc2, 0x8b, - 0x65, 0x4c, 0x49, 0xa0, 0x0a, 0xf4, 0x33, 0x37, 0x36, 0xc1, 0xcf, 0x64, 0xbe, 0xdc, 0x3a, 0xb8, - 0x83, 0xf2, 0x48, 0x1c, 0x0c, 0x01, 0x73, 0x42, 0x68, 0x03, 0x06, 0x6a, 0x2c, 0x2f, 0xa9, 0x60, - 0x60, 0x3e, 0x90, 0x29, 0x6b, 0xee, 0x90, 0xb0, 0x55, 0x88, 0x5e, 0x19, 0x06, 0x16, 0xb4, 0x18, - 0x55, 0xd2, 0xda, 0xd9, 0x0a, 0x45, 0xde, 0xee, 0x6c, 0xaa, 0x1d, 0xf2, 0x10, 0x0b, 0xaa, 0x0c, - 0x03, 0x0b, 0x5a, 0xe8, 0x55, 0x28, 0x6c, 0xd5, 0x84, 0x8b, 0x5a, 0xa6, 0xd0, 0xd9, 0x8c, 0x93, - 0xb2, 0x38, 0x70, 0xff, 0x60, 0xb6, 0xb0, 0xb2, 0x84, 0x0b, 0x5b, 0x35, 0xb4, 0x0e, 0x83, 0x5b, - 0x3c, 0xb2, 0x82, 0x90, 0x2b, 0x3f, 0x9d, 0x1d, 0xf4, 0x21, 0x15, 0x7c, 0x81, 0xbb, 0x3b, 0x09, - 0x00, 0x96, 0x44, 0x58, 0x32, 0x02, 0x15, 0x21, 0x42, 0x04, 0xa8, 0x9b, 0x3b, 0x5a, 0x54, 0x0f, - 0xce, 0x5f, 0xc6, 0x71, 0x26, 0xb0, 0x46, 0x91, 0xae, 0x6a, 0xe7, 0x5e, 0x3b, 0x60, 0x51, 0xc0, - 0x45, 0x24, 0xa3, 0xcc, 0x55, 0xbd, 0x20, 0x91, 0x3a, 0xad, 0x6a, 0x85, 0x84, 0x63, 0xa2, 0x68, - 0x17, 0x46, 0xf7, 0xc2, 0xd6, 0x0e, 0x91, 0x5b, 0x9a, 0x05, 0x36, 0xca, 0xe1, 0x8f, 0x6e, 0x09, - 0x44, 0x37, 0x88, 0xda, 0x4e, 0x23, 0x75, 0x0a, 0x31, 0x5e, 0xf6, 0x96, 0x4e, 0x0c, 0x9b, 0xb4, - 0xe9, 0xf0, 0xbf, 0xdd, 0xf6, 0x37, 0xf7, 0x23, 0x22, 0xe2, 0xca, 0x65, 0x0e, 0xff, 0x9b, 0x1c, - 0x25, 0x3d, 0xfc, 0x02, 0x80, 0x25, 0x11, 0x74, 0x4b, 0x0c, 0x0f, 0x3b, 0x3d, 0x27, 0xf2, 0x83, - 0xbf, 0x2e, 0x48, 0xa4, 0x9c, 0x41, 0x61, 0xa7, 0x65, 0x4c, 0x8a, 0x9d, 0x92, 0xad, 0x1d, 0x3f, - 0xf2, 0xbd, 0xc4, 0x09, 0x3d, 0x99, 0x7f, 0x4a, 0x56, 0x32, 0xf0, 0xd3, 0xa7, 0x64, 0x16, 0x16, - 0xce, 0x6c, 0x0b, 0xd5, 0x61, 0xac, 0xe5, 0x07, 0xd1, 0x1d, 0x3f, 0x90, 0xeb, 0x0b, 0x75, 0x90, - 0x8b, 0x19, 0x98, 0xa2, 0x45, 0x16, 0xb2, 0xd1, 0x84, 0xe0, 0x04, 0x4d, 0xf4, 0x31, 0x18, 0x0c, - 0x6b, 0x4e, 0x83, 0xac, 0xde, 0x98, 0x9e, 0xca, 0xbf, 0x7e, 0xaa, 0x1c, 0x25, 0x67, 0x75, 0xf1, - 0xc0, 0x18, 0x1c, 0x05, 0x4b, 0x72, 0x68, 0x05, 0xfa, 0x59, 0xb2, 0x39, 0x16, 0x04, 0x31, 0x27, - 0x86, 0x6d, 0xca, 0x00, 0x9e, 0x9f, 0x4d, 0xac, 0x18, 0xf3, 0xea, 0x74, 0x0f, 0x88, 0xe7, 0xa1, - 0x1f, 0x4e, 0x9f, 0xce, 0xdf, 0x03, 0xe2, 0x55, 0x79, 0xa3, 0xda, 0x69, 0x0f, 0x28, 0x24, 0x1c, - 0x13, 0xa5, 0x27, 0x33, 0x3d, 0x4d, 0xcf, 0x74, 0xb0, 0xdc, 0xca, 0x3d, 0x4b, 0xd9, 0xc9, 0x4c, - 0x4f, 0x52, 0x4a, 0xc2, 0xfe, 0xbd, 0xc1, 0x34, 0xcf, 0xc2, 0x04, 0x0a, 0xdf, 0x67, 0xa5, 0x74, - 0xcd, 0x1f, 0xec, 0x55, 0xbe, 0x79, 0x8c, 0x4f, 0xa1, 0xcf, 0x59, 0x70, 0xa6, 0x95, 0xf9, 0x21, - 0x82, 0x01, 0xe8, 0x4d, 0x4c, 0xca, 0x3f, 0x5d, 0x05, 0xcc, 0xcc, 0x86, 0xe3, 0x9c, 0x96, 0x92, - 0xcf, 0xcd, 0xe2, 0x3b, 0x7e, 0x6e, 0xae, 0xc1, 0x50, 0x8d, 0x3f, 0x45, 0x3a, 0xe6, 0xe9, 0x4e, - 0xbe, 0xbd, 0x19, 0x2b, 0x21, 0xde, 0x30, 0x5b, 0x58, 0x91, 0x40, 0x3f, 0x6a, 0xc1, 0xb9, 0x64, - 0xd7, 0x31, 0x61, 0x60, 0x11, 0x65, 0x93, 0xcb, 0x32, 0x56, 0xc4, 0xf7, 0xa7, 0xf8, 0x7f, 0x03, - 0xf9, 0xb0, 0x1b, 0x02, 0xee, 0xdc, 0x18, 0x2a, 0x67, 0x08, 0x53, 0x06, 0x4c, 0x05, 0x52, 0x0f, - 0x02, 0x95, 0x97, 0x60, 0xa4, 0xe9, 0xb7, 0xbd, 0x48, 0x18, 0x7a, 0x09, 0xa3, 0x13, 0x66, 0x6c, - 0xb1, 0xa6, 0x95, 0x63, 0x03, 0x2b, 0x21, 0x86, 0x19, 0x7a, 0x60, 0x31, 0xcc, 0x5b, 0x30, 0xe2, - 0x69, 0x96, 0xc9, 0x82, 0x1f, 0xb8, 0x98, 0x1f, 0x21, 0x57, 0xb7, 0x63, 0xe6, 0xbd, 0xd4, 0x4b, - 0xb0, 0x41, 0xed, 0x64, 0x2d, 0xc0, 0xbe, 0x64, 0x65, 0x30, 0xf5, 0x5c, 0x14, 0xf3, 0x61, 0x53, - 0x14, 0x73, 0x31, 0x29, 0x8a, 0x49, 0x29, 0x0f, 0x0c, 0x29, 0x4c, 0xef, 0x09, 0x80, 0x7a, 0x8d, - 0xb2, 0x69, 0x37, 0xe0, 0x42, 0xb7, 0x6b, 0x89, 0x59, 0xfc, 0xd5, 0x95, 0xaa, 0x38, 0xb6, 0xf8, - 0xab, 0xaf, 0x96, 0x31, 0x83, 0xf4, 0x1a, 0xbf, 0xc9, 0xfe, 0x4f, 0x16, 0x14, 0x2b, 0x7e, 0xfd, - 0x04, 0x1e, 0xbc, 0x1f, 0x31, 0x1e, 0xbc, 0x8f, 0x66, 0x5f, 0x88, 0xf5, 0x5c, 0xd5, 0xc7, 0x72, - 0x42, 0xf5, 0x71, 0x2e, 0x8f, 0x40, 0x67, 0x45, 0xc7, 0x4f, 0x17, 0x61, 0xb8, 0xe2, 0xd7, 0x95, - 0xb9, 0xfd, 0x3f, 0x7e, 0x10, 0x73, 0xfb, 0xdc, 0x34, 0x16, 0x1a, 0x65, 0x66, 0x28, 0x28, 0x3d, - 0x8d, 0xbf, 0xc5, 0xac, 0xee, 0x6f, 0x13, 0x77, 0x7b, 0x27, 0x22, 0xf5, 0xe4, 0xe7, 0x9c, 0x9c, - 0xd5, 0xfd, 0xef, 0x15, 0x60, 0x3c, 0xd1, 0x3a, 0x6a, 0xc0, 0x68, 0x43, 0x17, 0xac, 0x8b, 0x75, - 0xfa, 0x40, 0x32, 0x79, 0x61, 0xb5, 0xac, 0x15, 0x61, 0x93, 0x38, 0x9a, 0x03, 0x50, 0x9a, 0x66, - 0x29, 0x5e, 0x65, 0x5c, 0xbf, 0x52, 0x45, 0x87, 0x58, 0xc3, 0x40, 0x2f, 0xc3, 0x70, 0xe4, 0xb7, - 0xfc, 0x86, 0xbf, 0xbd, 0x7f, 0x8d, 0xc8, 0xd0, 0x5e, 0xca, 0x16, 0x71, 0x23, 0x06, 0x61, 0x1d, - 0x0f, 0xdd, 0x85, 0x49, 0x45, 0xa4, 0x7a, 0x0c, 0xca, 0x06, 0x26, 0x55, 0x58, 0x4f, 0x52, 0xc4, - 0xe9, 0x46, 0xec, 0x9f, 0x2b, 0xf2, 0x21, 0xf6, 0x22, 0xf7, 0xbd, 0xdd, 0xf0, 0xee, 0xde, 0x0d, - 0x5f, 0xb7, 0x60, 0x82, 0xb6, 0xce, 0x0c, 0xad, 0xe4, 0x35, 0xaf, 0x62, 0x72, 0x5b, 0x1d, 0x62, - 0x72, 0x5f, 0xa4, 0xa7, 0x66, 0xdd, 0x6f, 0x47, 0x42, 0x76, 0xa7, 0x1d, 0x8b, 0xb4, 0x14, 0x0b, - 0xa8, 0xc0, 0x23, 0x41, 0x20, 0x9c, 0x43, 0x75, 0x3c, 0x12, 0x04, 0x58, 0x40, 0x65, 0xc8, 0xee, - 0xbe, 0xec, 0x90, 0xdd, 0x3c, 0xf2, 0xaa, 0x30, 0xc9, 0x11, 0x0c, 0x97, 0x16, 0x79, 0x55, 0xda, - 0xea, 0xc4, 0x38, 0xf6, 0x57, 0x8b, 0x30, 0x52, 0xf1, 0xeb, 0xb1, 0x96, 0xf9, 0x25, 0x43, 0xcb, - 0x7c, 0x21, 0xa1, 0x65, 0x9e, 0xd0, 0x71, 0xdf, 0xd3, 0x29, 0x7f, 0xb3, 0x74, 0xca, 0xff, 0xc0, - 0x62, 0xb3, 0x56, 0x5e, 0xaf, 0x72, 0xbb, 0x3d, 0x74, 0x19, 0x86, 0xd9, 0x01, 0xc3, 0xbc, 0x91, - 0xa5, 0xea, 0x95, 0xa5, 0xa2, 0x5a, 0x8f, 0x8b, 0xb1, 0x8e, 0x83, 0x2e, 0xc1, 0x50, 0x48, 0x9c, - 0xa0, 0xb6, 0xa3, 0x4e, 0x57, 0xa1, 0x27, 0xe5, 0x65, 0x58, 0x41, 0xd1, 0x9b, 0x71, 0xd0, 0xcf, - 0x62, 0xbe, 0x77, 0xa3, 0xde, 0x1f, 0xbe, 0x45, 0xf2, 0x23, 0x7d, 0xda, 0xb7, 0x01, 0xa5, 0xf1, - 0x7b, 0x08, 0x4b, 0x37, 0x6b, 0x86, 0xa5, 0x2b, 0xa5, 0x42, 0xd2, 0xfd, 0x99, 0x05, 0x63, 0x15, - 0xbf, 0x4e, 0xb7, 0xee, 0xb7, 0xd3, 0x3e, 0xd5, 0x23, 0x1e, 0x0f, 0x74, 0x88, 0x78, 0xfc, 0x04, - 0xf4, 0x57, 0xfc, 0xfa, 0x6a, 0xa5, 0x53, 0x68, 0x01, 0xfb, 0xaf, 0x59, 0x30, 0x58, 0xf1, 0xeb, - 0x27, 0xa0, 0x16, 0xf8, 0xb0, 0xa9, 0x16, 0x78, 0x24, 0x67, 0xdd, 0xe4, 0x68, 0x02, 0xfe, 0x4a, - 0x1f, 0x8c, 0xd2, 0x7e, 0xfa, 0xdb, 0x72, 0x2a, 0x8d, 0x61, 0xb3, 0x7a, 0x18, 0x36, 0xca, 0x85, - 0xfb, 0x8d, 0x86, 0x7f, 0x27, 0x39, 0xad, 0x2b, 0xac, 0x14, 0x0b, 0x28, 0x7a, 0x0e, 0x86, 0x5a, - 0x01, 0xd9, 0x73, 0x7d, 0xc1, 0xde, 0x6a, 0x4a, 0x96, 0x8a, 0x28, 0xc7, 0x0a, 0x83, 0x3e, 0x0b, - 0x43, 0xd7, 0xa3, 0x57, 0x79, 0xcd, 0xf7, 0xea, 0x5c, 0x72, 0x5e, 0x14, 0x69, 0x39, 0xb4, 0x72, - 0x6c, 0x60, 0xa1, 0xdb, 0x50, 0x62, 0xff, 0xd9, 0xb1, 0x73, 0xf4, 0x04, 0xaf, 0x22, 0xe1, 0x9f, - 0x20, 0x80, 0x63, 0x5a, 0xe8, 0x05, 0x80, 0x48, 0x86, 0xb6, 0x0f, 0x45, 0xa0, 0x35, 0xf5, 0x14, - 0x50, 0x41, 0xef, 0x43, 0xac, 0x61, 0xa1, 0x67, 0xa1, 0x14, 0x39, 0x6e, 0xe3, 0xba, 0xeb, 0x91, - 0x90, 0x49, 0xc4, 0x8b, 0x32, 0xef, 0x9e, 0x28, 0xc4, 0x31, 0x9c, 0xb2, 0x62, 0x2c, 0x08, 0x07, - 0x4f, 0x0f, 0x3d, 0xc4, 0xb0, 0x19, 0x2b, 0x76, 0x5d, 0x95, 0x62, 0x0d, 0x03, 0xed, 0xc0, 0x63, - 0xae, 0xc7, 0x52, 0x58, 0x90, 0xea, 0xae, 0xdb, 0xda, 0xb8, 0x5e, 0xbd, 0x45, 0x02, 0x77, 0x6b, - 0x7f, 0xd1, 0xa9, 0xed, 0x12, 0x4f, 0xa6, 0xee, 0x7c, 0x52, 0x74, 0xf1, 0xb1, 0xd5, 0x0e, 0xb8, - 0xb8, 0x23, 0x25, 0xfb, 0x45, 0xb6, 0xde, 0x6f, 0x54, 0xd1, 0xfb, 0x8d, 0xa3, 0xe3, 0x8c, 0x7e, - 0x74, 0x1c, 0x1e, 0xcc, 0x0e, 0xdc, 0xa8, 0x6a, 0x31, 0x24, 0x5e, 0x81, 0xd3, 0x15, 0xbf, 0x5e, - 0xf1, 0x83, 0x68, 0xc5, 0x0f, 0xee, 0x38, 0x41, 0x5d, 0x2e, 0xaf, 0x59, 0x19, 0x45, 0x83, 0x9e, - 0x9f, 0xfd, 0xfc, 0x74, 0x31, 0x22, 0x64, 0xbc, 0xc8, 0x38, 0xb6, 0x23, 0xfa, 0x7e, 0xd5, 0x18, - 0xef, 0xa0, 0x92, 0xc0, 0x5c, 0x71, 0x22, 0x82, 0x6e, 0xb0, 0xe4, 0xd6, 0xf1, 0x35, 0x2a, 0xaa, - 0x3f, 0xa3, 0x25, 0xb7, 0x8e, 0x81, 0x99, 0xf7, 0xae, 0x59, 0xdf, 0x7e, 0x19, 0x26, 0xe9, 0xdb, - 0x4b, 0x31, 0x32, 0xac, 0x95, 0xee, 0xe1, 0x34, 0xfe, 0x73, 0x3f, 0x3b, 0x88, 0x13, 0xf9, 0x47, - 0xd0, 0xa7, 0x60, 0x2c, 0x24, 0xd7, 0x5d, 0xaf, 0x7d, 0x57, 0x4a, 0x3e, 0x3a, 0x38, 0xfd, 0x55, - 0x97, 0x75, 0x4c, 0x2e, 0x3f, 0x35, 0xcb, 0x70, 0x82, 0x1a, 0x6a, 0xc2, 0xd8, 0x1d, 0xd7, 0xab, - 0xfb, 0x77, 0x42, 0x49, 0x7f, 0x28, 0x5f, 0x8c, 0x7a, 0x9b, 0x63, 0x26, 0xfa, 0x68, 0x34, 0x77, - 0xdb, 0x20, 0x86, 0x13, 0xc4, 0xe9, 0x62, 0x0f, 0xda, 0xde, 0x42, 0x78, 0x33, 0x24, 0x81, 0xc8, - 0x6e, 0xce, 0x16, 0x3b, 0x96, 0x85, 0x38, 0x86, 0xd3, 0xc5, 0xce, 0xfe, 0x5c, 0x09, 0xfc, 0x36, - 0x4f, 0x76, 0x21, 0x16, 0x3b, 0x56, 0xa5, 0x58, 0xc3, 0xa0, 0x87, 0x01, 0xfb, 0xb7, 0xee, 0x7b, - 0xd8, 0xf7, 0x23, 0x79, 0x7c, 0x30, 0x53, 0x00, 0xad, 0x1c, 0x1b, 0x58, 0x68, 0x05, 0x50, 0xd8, - 0x6e, 0xb5, 0x1a, 0xcc, 0x9a, 0xc8, 0x69, 0x30, 0x52, 0xdc, 0xcc, 0xa2, 0xc8, 0x83, 0xf5, 0x56, - 0x53, 0x50, 0x9c, 0x51, 0x83, 0xde, 0x0b, 0x5b, 0xa2, 0xab, 0xfd, 0xac, 0xab, 0x5c, 0xe5, 0x52, - 0xe5, 0xfd, 0x94, 0x30, 0xb4, 0x0c, 0x83, 0xe1, 0x7e, 0x58, 0x8b, 0x44, 0x6c, 0xc5, 0x9c, 0x14, - 0x53, 0x55, 0x86, 0xa2, 0x65, 0x38, 0xe4, 0x55, 0xb0, 0xac, 0x8b, 0x6a, 0x30, 0x25, 0x28, 0x2e, - 0xed, 0x38, 0x9e, 0x4a, 0xd8, 0xc3, 0x8d, 0xaa, 0x2f, 0xdf, 0x3f, 0x98, 0x9d, 0x12, 0x2d, 0xeb, - 0xe0, 0xc3, 0x83, 0xd9, 0x33, 0x15, 0xbf, 0x9e, 0x01, 0xc1, 0x59, 0xd4, 0xf8, 0xe2, 0xab, 0xd5, - 0xfc, 0x66, 0xab, 0x12, 0xf8, 0x5b, 0x6e, 0x83, 0x74, 0x52, 0x5b, 0x55, 0x0d, 0x4c, 0xb1, 0xf8, - 0x8c, 0x32, 0x9c, 0xa0, 0x66, 0x7f, 0x37, 0xe3, 0x9d, 0x58, 0x42, 0xef, 0xa8, 0x1d, 0x10, 0xd4, - 0x84, 0xd1, 0x16, 0xdb, 0x5d, 0x22, 0x05, 0x85, 0x58, 0xeb, 0x2f, 0xf5, 0x28, 0x7e, 0xb9, 0x43, - 0xaf, 0x1c, 0xd3, 0x34, 0xa9, 0xa2, 0x93, 0xc3, 0x26, 0x75, 0xfb, 0x3f, 0x4c, 0xb3, 0xdb, 0xb7, - 0xca, 0x65, 0x2a, 0x83, 0xc2, 0x87, 0x43, 0x3c, 0xe3, 0x66, 0xf2, 0x85, 0x7b, 0xf1, 0xb4, 0x08, - 0x3f, 0x10, 0x2c, 0xeb, 0xa2, 0x4f, 0xc2, 0x18, 0x7d, 0x15, 0xa9, 0x1b, 0x30, 0x9c, 0x3e, 0x95, - 0x1f, 0x6b, 0x43, 0x61, 0xe9, 0xe9, 0x69, 0xf4, 0xca, 0x38, 0x41, 0x0c, 0xbd, 0xc9, 0x4c, 0x81, - 0x24, 0xe9, 0x42, 0x2f, 0xa4, 0x75, 0xab, 0x1f, 0x49, 0x56, 0x23, 0x82, 0xda, 0x30, 0x95, 0x4e, - 0x66, 0x17, 0x4e, 0xdb, 0xf9, 0xec, 0x65, 0x3a, 0x1f, 0x5d, 0x9c, 0x47, 0x24, 0x0d, 0x0b, 0x71, - 0x16, 0x7d, 0x74, 0x1d, 0x46, 0x45, 0x56, 0x6b, 0xb1, 0x72, 0x8b, 0x86, 0xcc, 0x71, 0x14, 0xeb, - 0xc0, 0xc3, 0x64, 0x01, 0x36, 0x2b, 0xa3, 0x6d, 0x38, 0xa7, 0x65, 0x99, 0xba, 0x12, 0x38, 0xcc, - 0x70, 0xc0, 0x65, 0xc7, 0xa9, 0xc6, 0x17, 0x3c, 0x7e, 0xff, 0x60, 0xf6, 0xdc, 0x46, 0x27, 0x44, - 0xdc, 0x99, 0x0e, 0xba, 0x01, 0xa7, 0xb9, 0xa7, 0x78, 0x99, 0x38, 0xf5, 0x86, 0xeb, 0x29, 0xc6, - 0x83, 0x6f, 0xf9, 0xb3, 0xf7, 0x0f, 0x66, 0x4f, 0x2f, 0x64, 0x21, 0xe0, 0xec, 0x7a, 0xe8, 0xc3, - 0x50, 0xaa, 0x7b, 0xa1, 0x18, 0x83, 0x01, 0x23, 0x91, 0x57, 0xa9, 0xbc, 0x5e, 0x55, 0xdf, 0x1f, - 0xff, 0xc1, 0x71, 0x05, 0xb4, 0xcd, 0xe5, 0xd2, 0x4a, 0x5a, 0x32, 0x98, 0x8a, 0x94, 0x95, 0x14, - 0x28, 0x1a, 0xbe, 0xa2, 0x5c, 0x21, 0xa3, 0x5c, 0x28, 0x0c, 0x37, 0x52, 0x83, 0x30, 0x7a, 0x03, - 0x90, 0x08, 0x18, 0xbf, 0x50, 0x63, 0xf9, 0x4d, 0x98, 0x18, 0x7f, 0xc8, 0xf4, 0x5e, 0xac, 0xa6, - 0x30, 0x70, 0x46, 0x2d, 0x74, 0x95, 0x9e, 0x2a, 0x7a, 0xa9, 0x38, 0xb5, 0x54, 0xda, 0xc5, 0x32, - 0x69, 0x05, 0x84, 0x19, 0x42, 0x99, 0x14, 0x71, 0xa2, 0x1e, 0xaa, 0xc3, 0x63, 0x4e, 0x3b, 0xf2, - 0x99, 0xc8, 0xdf, 0x44, 0xdd, 0xf0, 0x77, 0x89, 0xc7, 0xb4, 0x6d, 0x43, 0x8b, 0x17, 0x28, 0x67, - 0xb3, 0xd0, 0x01, 0x0f, 0x77, 0xa4, 0x42, 0x39, 0x52, 0x95, 0x67, 0x19, 0xcc, 0xf8, 0x5f, 0x19, - 0xb9, 0x96, 0x5f, 0x86, 0xe1, 0x1d, 0x3f, 0x8c, 0xd6, 0x49, 0x74, 0xc7, 0x0f, 0x76, 0x45, 0x1c, - 0xdb, 0x38, 0x2a, 0x78, 0x0c, 0xc2, 0x3a, 0x1e, 0x7d, 0x72, 0x32, 0x5b, 0x90, 0xd5, 0x32, 0x53, - 0xc3, 0x0f, 0xc5, 0x67, 0xcc, 0x55, 0x5e, 0x8c, 0x25, 0x5c, 0xa2, 0xae, 0x56, 0x96, 0x98, 0x4a, - 0x3d, 0x81, 0xba, 0x5a, 0x59, 0xc2, 0x12, 0x4e, 0x97, 0x6b, 0xb8, 0xe3, 0x04, 0xa4, 0x12, 0xf8, - 0x35, 0x12, 0x6a, 0xb1, 0xe8, 0x1f, 0xe5, 0x51, 0x7a, 0xe9, 0x72, 0xad, 0x66, 0x21, 0xe0, 0xec, - 0x7a, 0x88, 0xa4, 0x33, 0xac, 0x8d, 0xe5, 0xeb, 0x42, 0xd2, 0xfc, 0x4c, 0x8f, 0x49, 0xd6, 0x3c, - 0x98, 0x50, 0xb9, 0xdd, 0x78, 0x5c, 0xde, 0x70, 0x7a, 0x9c, 0xad, 0xed, 0xde, 0x83, 0xfa, 0x2a, - 0xed, 0xd2, 0x6a, 0x82, 0x12, 0x4e, 0xd1, 0x36, 0x42, 0xbc, 0x4d, 0x74, 0x0d, 0xf1, 0x36, 0x0f, - 0xa5, 0xb0, 0xbd, 0x59, 0xf7, 0x9b, 0x8e, 0xeb, 0x31, 0x95, 0xba, 0xf6, 0xf6, 0xa9, 0x4a, 0x00, - 0x8e, 0x71, 0xd0, 0x0a, 0x0c, 0x39, 0x52, 0x75, 0x84, 0xf2, 0x83, 0xfa, 0x28, 0x85, 0x11, 0x8f, - 0x73, 0x21, 0x95, 0x45, 0xaa, 0x2e, 0x7a, 0x0d, 0x46, 0x85, 0xa7, 0xb3, 0x48, 0x2b, 0x3a, 0x65, - 0xba, 0xa3, 0x55, 0x75, 0x20, 0x36, 0x71, 0xd1, 0x4d, 0x18, 0x8e, 0xfc, 0x06, 0xf3, 0xa9, 0xa2, - 0x6c, 0xde, 0x99, 0xfc, 0xf0, 0x74, 0x1b, 0x0a, 0x4d, 0x97, 0xda, 0xaa, 0xaa, 0x58, 0xa7, 0x83, - 0x36, 0xf8, 0x7a, 0x67, 0x91, 0xe7, 0x49, 0x38, 0xfd, 0x48, 0xfe, 0x9d, 0xa4, 0x02, 0xd4, 0x9b, - 0xdb, 0x41, 0xd4, 0xc4, 0x3a, 0x19, 0x74, 0x05, 0x26, 0x5b, 0x81, 0xeb, 0xb3, 0x35, 0xa1, 0xb4, - 0x86, 0xd3, 0x66, 0x9e, 0xa9, 0x4a, 0x12, 0x01, 0xa7, 0xeb, 0x30, 0x47, 0x75, 0x51, 0x38, 0x7d, - 0x96, 0xe7, 0xca, 0xe0, 0x4f, 0x49, 0x5e, 0x86, 0x15, 0x14, 0xad, 0xb1, 0x93, 0x98, 0x4b, 0x41, - 0xa6, 0x67, 0xf2, 0xe3, 0x08, 0xe9, 0xd2, 0x12, 0xce, 0xbc, 0xaa, 0xbf, 0x38, 0xa6, 0x80, 0xea, - 0x5a, 0x8a, 0x4a, 0xfa, 0x04, 0x08, 0xa7, 0x1f, 0xeb, 0x60, 0x90, 0x97, 0x78, 0x95, 0xc4, 0x0c, - 0x81, 0x51, 0x1c, 0xe2, 0x04, 0x4d, 0xf4, 0x51, 0x98, 0x10, 0xd1, 0x0f, 0xe3, 0x61, 0x3a, 0x17, - 0x5b, 0xaa, 0xe3, 0x04, 0x0c, 0xa7, 0xb0, 0x79, 0xae, 0x0a, 0x67, 0xb3, 0x41, 0xc4, 0xd1, 0x77, - 0xdd, 0xf5, 0x76, 0xc3, 0xe9, 0xf3, 0xec, 0x7c, 0x10, 0xb9, 0x2a, 0x92, 0x50, 0x9c, 0x51, 0x03, - 0x6d, 0xc0, 0x44, 0x2b, 0x20, 0xa4, 0xc9, 0x18, 0x7d, 0x71, 0x9f, 0xcd, 0xf2, 0x38, 0x0d, 0xb4, - 0x27, 0x95, 0x04, 0xec, 0x30, 0xa3, 0x0c, 0xa7, 0x28, 0xa0, 0x3b, 0x30, 0xe4, 0xef, 0x91, 0x60, - 0x87, 0x38, 0xf5, 0xe9, 0x0b, 0x1d, 0x3c, 0x27, 0xc4, 0xe5, 0x76, 0x43, 0xe0, 0x26, 0x2c, 0x0d, - 0x64, 0x71, 0x77, 0x4b, 0x03, 0xd9, 0x18, 0xfa, 0x7f, 0x2d, 0x38, 0x2b, 0x95, 0x13, 0xd5, 0x16, - 0x1d, 0xf5, 0x25, 0xdf, 0x0b, 0xa3, 0x80, 0x47, 0x16, 0x78, 0x3c, 0xdf, 0xdb, 0x7e, 0x23, 0xa7, - 0x92, 0x12, 0xc4, 0x9e, 0xcd, 0xc3, 0x08, 0x71, 0x7e, 0x8b, 0x68, 0x09, 0x26, 0x43, 0x12, 0xc9, - 0xc3, 0x68, 0x21, 0x5c, 0x79, 0xb3, 0xbc, 0x3e, 0xfd, 0x04, 0x0f, 0x8b, 0x40, 0x37, 0x43, 0x35, - 0x09, 0xc4, 0x69, 0x7c, 0x74, 0x19, 0x0a, 0x7e, 0x38, 0xfd, 0x64, 0x87, 0xac, 0xa6, 0xf4, 0x05, - 0xcf, 0x2d, 0xce, 0x6e, 0x54, 0x71, 0xc1, 0x0f, 0x65, 0xbe, 0x08, 0xfa, 0x1e, 0x0b, 0xa7, 0x9f, - 0xe2, 0x62, 0x3b, 0x99, 0x2f, 0x82, 0x15, 0xe2, 0x18, 0x8e, 0x76, 0x60, 0x3c, 0x34, 0xde, 0xbd, - 0xe1, 0xf4, 0x45, 0x36, 0x52, 0x4f, 0xe5, 0x4d, 0x9a, 0x81, 0xad, 0x85, 0x7b, 0x37, 0xa9, 0xe0, - 0x24, 0xd9, 0x99, 0xef, 0x84, 0xc9, 0x14, 0x23, 0x73, 0x94, 0x24, 0x45, 0x33, 0xbb, 0x30, 0x6a, - 0x2c, 0x96, 0x87, 0xaa, 0x73, 0xff, 0x67, 0x83, 0x50, 0x52, 0xfa, 0x58, 0x34, 0x6f, 0xaa, 0xd9, - 0xcf, 0x26, 0xd5, 0xec, 0x43, 0x15, 0xbf, 0x6e, 0x68, 0xd6, 0x37, 0x32, 0xc2, 0xda, 0xe5, 0x1d, - 0x4d, 0xbd, 0x9b, 0xfb, 0x6b, 0x42, 0xee, 0x62, 0xcf, 0xfa, 0xfa, 0xbe, 0x8e, 0x72, 0xf3, 0x2b, - 0x30, 0xe9, 0xf9, 0x8c, 0x7b, 0x26, 0x75, 0xc9, 0x1a, 0x31, 0x0e, 0xa8, 0xa4, 0xc7, 0x89, 0x49, - 0x20, 0xe0, 0x74, 0x1d, 0xda, 0x20, 0x67, 0x61, 0x92, 0x82, 0x7a, 0xce, 0xe1, 0x60, 0x01, 0x45, - 0x4f, 0x40, 0x7f, 0xcb, 0xaf, 0xaf, 0x56, 0x04, 0xe7, 0xac, 0x05, 0x53, 0xad, 0xaf, 0x56, 0x30, - 0x87, 0xa1, 0x05, 0x18, 0x60, 0x3f, 0xc2, 0xe9, 0x91, 0xfc, 0x80, 0x20, 0xac, 0x86, 0x96, 0x02, - 0x8a, 0x55, 0xc0, 0xa2, 0x22, 0x13, 0x18, 0xd2, 0xe7, 0x06, 0x13, 0x18, 0x0e, 0x3e, 0xa0, 0xc0, - 0x50, 0x12, 0xc0, 0x31, 0x2d, 0x74, 0x17, 0x4e, 0x1b, 0x4f, 0x3c, 0xbe, 0x44, 0x48, 0x28, 0x82, - 0x12, 0x3c, 0xd1, 0xf1, 0x6d, 0x27, 0xf4, 0xfb, 0xe7, 0x44, 0xa7, 0x4f, 0xaf, 0x66, 0x51, 0xc2, - 0xd9, 0x0d, 0xa0, 0x06, 0x4c, 0xd6, 0x52, 0xad, 0x0e, 0xf5, 0xde, 0xaa, 0x9a, 0xd0, 0x74, 0x8b, - 0x69, 0xc2, 0xe8, 0x35, 0x18, 0x7a, 0xdb, 0x0f, 0xd9, 0xad, 0x23, 0xb8, 0x7d, 0xe9, 0xd1, 0x3e, - 0xf4, 0xe6, 0x8d, 0x2a, 0x2b, 0x3f, 0x3c, 0x98, 0x1d, 0xae, 0xf8, 0x75, 0xf9, 0x17, 0xab, 0x0a, - 0xe8, 0x07, 0x2d, 0x98, 0x49, 0xbf, 0x21, 0x55, 0xa7, 0x47, 0x7b, 0xef, 0xb4, 0x2d, 0x1a, 0x9d, - 0x59, 0xce, 0x25, 0x87, 0x3b, 0x34, 0x65, 0xff, 0xb2, 0xc5, 0xc4, 0x8e, 0x42, 0x6f, 0x46, 0xc2, - 0x76, 0xe3, 0x24, 0x32, 0xdf, 0x2e, 0x1b, 0x2a, 0xbd, 0x07, 0xb6, 0xf7, 0xf8, 0x47, 0x16, 0xb3, - 0xf7, 0x38, 0x41, 0xc7, 0x8e, 0x37, 0x61, 0x28, 0x92, 0x19, 0x89, 0x3b, 0x24, 0xeb, 0xd5, 0x3a, - 0xc5, 0x6c, 0x5e, 0x14, 0xef, 0xad, 0x92, 0x0f, 0x2b, 0x32, 0xf6, 0xdf, 0xe5, 0x33, 0x20, 0x21, - 0x27, 0xa0, 0x39, 0x29, 0x9b, 0x9a, 0x93, 0xd9, 0x2e, 0x5f, 0x90, 0xa3, 0x41, 0xf9, 0x3b, 0x66, - 0xbf, 0x99, 0xcc, 0xe9, 0xdd, 0x6e, 0x68, 0x64, 0x7f, 0xde, 0x02, 0x88, 0x63, 0x55, 0xf7, 0x90, - 0x73, 0xee, 0x15, 0xca, 0x6d, 0xfb, 0x91, 0x5f, 0xf3, 0x1b, 0x42, 0x2f, 0xf8, 0x58, 0xac, 0xbc, - 0xe1, 0xe5, 0x87, 0xda, 0x6f, 0xac, 0xb0, 0xd1, 0xac, 0x8c, 0x8c, 0x57, 0x8c, 0xd5, 0x89, 0x46, - 0x54, 0xbc, 0x2f, 0x5a, 0x70, 0x2a, 0xcb, 0x4a, 0x98, 0xbe, 0xdd, 0xb8, 0xf4, 0x4d, 0x19, 0x81, - 0xa9, 0xd9, 0xbc, 0x25, 0xca, 0xb1, 0xc2, 0xe8, 0x39, 0x99, 0xdf, 0xd1, 0x82, 0x44, 0xdf, 0x80, - 0xd1, 0x4a, 0x40, 0xb4, 0xcb, 0xf5, 0x75, 0x1e, 0x6d, 0x81, 0xf7, 0xe7, 0xb9, 0x23, 0x47, 0x5a, - 0xb0, 0xbf, 0x5c, 0x80, 0x53, 0xdc, 0x96, 0x62, 0x61, 0xcf, 0x77, 0xeb, 0x15, 0xbf, 0x2e, 0x7c, - 0xc1, 0x3e, 0x01, 0x23, 0x2d, 0x4d, 0x64, 0xda, 0x29, 0xe0, 0xa9, 0x2e, 0x5a, 0x8d, 0x85, 0x3c, - 0x7a, 0x29, 0x36, 0x68, 0xa1, 0x3a, 0x8c, 0x90, 0x3d, 0xb7, 0xa6, 0x14, 0xf2, 0x85, 0x23, 0x5f, - 0x74, 0xaa, 0x95, 0x65, 0x8d, 0x0e, 0x36, 0xa8, 0x3e, 0x84, 0x14, 0xdb, 0xf6, 0x8f, 0x5b, 0xf0, - 0x48, 0x4e, 0x78, 0x54, 0xda, 0xdc, 0x1d, 0x66, 0xb5, 0x22, 0x96, 0xad, 0x6a, 0x8e, 0xdb, 0xb2, - 0x60, 0x01, 0x45, 0x1f, 0x03, 0xe0, 0xb6, 0x28, 0xc4, 0xab, 0x75, 0x8d, 0x23, 0x69, 0x84, 0xc0, - 0xd3, 0xa2, 0x99, 0xc9, 0xfa, 0x58, 0xa3, 0x65, 0x7f, 0xb1, 0x0f, 0xfa, 0x99, 0xed, 0x03, 0xaa, - 0xc0, 0xe0, 0x0e, 0x4f, 0x78, 0xd3, 0x71, 0xde, 0x28, 0xae, 0xcc, 0xa1, 0x13, 0xcf, 0x9b, 0x56, - 0x8a, 0x25, 0x19, 0xb4, 0x06, 0x53, 0x3c, 0xef, 0x50, 0xa3, 0x4c, 0x1a, 0xce, 0xbe, 0x94, 0x46, - 0xf2, 0x24, 0xb9, 0x4a, 0x2a, 0xbb, 0x9a, 0x46, 0xc1, 0x59, 0xf5, 0xd0, 0xeb, 0x30, 0x46, 0x5f, - 0x87, 0x7e, 0x3b, 0x92, 0x94, 0x78, 0xc6, 0x21, 0xf5, 0x1c, 0xdd, 0x30, 0xa0, 0x38, 0x81, 0x8d, - 0x5e, 0x83, 0xd1, 0x56, 0x4a, 0xee, 0xda, 0x1f, 0x0b, 0x28, 0x4c, 0x59, 0xab, 0x89, 0xcb, 0x0c, - 0x85, 0xdb, 0xcc, 0x2c, 0x7a, 0x63, 0x27, 0x20, 0xe1, 0x8e, 0xdf, 0xa8, 0x33, 0xf6, 0xaf, 0x5f, - 0x33, 0x14, 0x4e, 0xc0, 0x71, 0xaa, 0x06, 0xa5, 0xb2, 0xe5, 0xb8, 0x8d, 0x76, 0x40, 0x62, 0x2a, - 0x03, 0x26, 0x95, 0x95, 0x04, 0x1c, 0xa7, 0x6a, 0x74, 0x17, 0x28, 0x0f, 0x1e, 0x8f, 0x40, 0xd9, - 0xfe, 0x99, 0x02, 0x18, 0x53, 0xfb, 0xed, 0x9b, 0x09, 0x89, 0x7e, 0xd9, 0x76, 0xd0, 0xaa, 0x09, - 0x3b, 0x9f, 0xcc, 0x2f, 0x8b, 0x13, 0x9c, 0xf2, 0x2f, 0xa3, 0xff, 0x31, 0xab, 0x45, 0xf7, 0xf8, - 0xe9, 0x4a, 0xe0, 0xd3, 0x4b, 0x4e, 0xc6, 0xe3, 0x52, 0xf6, 0xf8, 0x83, 0xd2, 0x57, 0xb9, 0x43, - 0xe4, 0x4a, 0x61, 0xb1, 0xcc, 0x29, 0x18, 0x26, 0x31, 0x55, 0x11, 0x34, 0x40, 0x52, 0x41, 0x97, - 0x61, 0x58, 0xa4, 0xb7, 0x61, 0x66, 0xe3, 0x7c, 0x33, 0x31, 0x13, 0x9e, 0x72, 0x5c, 0x8c, 0x75, - 0x1c, 0xfb, 0x87, 0x0a, 0x30, 0x95, 0xe1, 0xf7, 0xc3, 0xaf, 0x91, 0x6d, 0x37, 0x8c, 0x54, 0x0e, - 0x55, 0xed, 0x1a, 0xe1, 0xe5, 0x58, 0x61, 0xd0, 0xb3, 0x8a, 0x5f, 0x54, 0xc9, 0xcb, 0x49, 0xd8, - 0xd5, 0x0b, 0xe8, 0x11, 0xb3, 0x91, 0x5e, 0x80, 0xbe, 0x76, 0x48, 0x64, 0xcc, 0x59, 0x75, 0x6d, - 0x33, 0x6d, 0x2b, 0x83, 0xd0, 0x67, 0xd4, 0xb6, 0x52, 0x5c, 0x6a, 0xcf, 0x28, 0xae, 0xba, 0xe4, - 0x30, 0xda, 0xb9, 0x88, 0x78, 0x8e, 0x17, 0x89, 0xc7, 0x56, 0x1c, 0x3c, 0x91, 0x95, 0x62, 0x01, - 0xb5, 0xbf, 0x50, 0x84, 0xb3, 0xb9, 0x9e, 0x80, 0xb4, 0xeb, 0x4d, 0xdf, 0x73, 0x23, 0x5f, 0xd9, - 0x46, 0xf1, 0x80, 0x89, 0xa4, 0xb5, 0xb3, 0x26, 0xca, 0xb1, 0xc2, 0x40, 0x17, 0xa1, 0x9f, 0xc9, - 0x6a, 0x53, 0xd9, 0x64, 0x17, 0xcb, 0x3c, 0x82, 0x16, 0x07, 0xf7, 0x9c, 0x00, 0xfc, 0x09, 0xca, - 0xc1, 0xf8, 0x8d, 0xe4, 0x85, 0x42, 0xbb, 0xeb, 0xfb, 0x0d, 0xcc, 0x80, 0xe8, 0x29, 0x31, 0x5e, - 0x09, 0x63, 0x20, 0xec, 0xd4, 0xfd, 0x50, 0x1b, 0xb4, 0x67, 0x60, 0x70, 0x97, 0xec, 0x07, 0xae, - 0xb7, 0x9d, 0x34, 0x12, 0xbb, 0xc6, 0x8b, 0xb1, 0x84, 0x9b, 0xe9, 0x0f, 0x07, 0x8f, 0x3b, 0x73, - 0xf7, 0x50, 0x57, 0xf6, 0xe4, 0x47, 0x8a, 0x30, 0x8e, 0x17, 0xcb, 0xef, 0x4d, 0xc4, 0xcd, 0xf4, - 0x44, 0x1c, 0x77, 0xe6, 0xee, 0xee, 0xb3, 0xf1, 0x0b, 0x16, 0x8c, 0xb3, 0x24, 0x3b, 0xc2, 0xdf, - 0xdf, 0xf5, 0xbd, 0x13, 0x78, 0x0a, 0x3c, 0x01, 0xfd, 0x01, 0x6d, 0x34, 0x99, 0x46, 0x96, 0xf5, - 0x04, 0x73, 0x18, 0x7a, 0x0c, 0xfa, 0x58, 0x17, 0xe8, 0xe4, 0x8d, 0xf0, 0x23, 0xb8, 0xec, 0x44, - 0x0e, 0x66, 0xa5, 0x2c, 0x7e, 0x14, 0x26, 0xad, 0x86, 0xcb, 0x3b, 0x1d, 0x6b, 0xd2, 0xdf, 0x1d, - 0x31, 0x02, 0x32, 0xbb, 0xf6, 0xce, 0xe2, 0x47, 0x65, 0x93, 0xec, 0xfc, 0xcc, 0xfe, 0xa3, 0x02, - 0x9c, 0xcf, 0xac, 0xd7, 0x73, 0xfc, 0xa8, 0xce, 0xb5, 0x1f, 0x66, 0x1a, 0x95, 0xe2, 0x09, 0x9a, - 0xe0, 0xf6, 0xf5, 0xca, 0xfd, 0xf7, 0xf7, 0x10, 0xd6, 0x29, 0x73, 0xc8, 0xde, 0x25, 0x61, 0x9d, - 0x32, 0xfb, 0x96, 0x23, 0x26, 0xf8, 0xf3, 0x42, 0xce, 0xb7, 0x30, 0x81, 0xc1, 0x25, 0x7a, 0xce, - 0x30, 0x60, 0x28, 0x1f, 0xe1, 0xfc, 0x8c, 0xe1, 0x65, 0x58, 0x41, 0xd1, 0x02, 0x8c, 0x37, 0x5d, - 0x8f, 0x1e, 0x3e, 0xfb, 0x26, 0x2b, 0xae, 0x44, 0xec, 0x6b, 0x26, 0x18, 0x27, 0xf1, 0x91, 0xab, - 0x85, 0x7c, 0xe2, 0x5f, 0xf7, 0xda, 0x91, 0x76, 0xdd, 0x9c, 0x69, 0x65, 0xa0, 0x46, 0x31, 0x23, - 0xfc, 0xd3, 0x9a, 0x26, 0x27, 0x2a, 0xf6, 0x2e, 0x27, 0x1a, 0xc9, 0x96, 0x11, 0xcd, 0xbc, 0x06, - 0xa3, 0x0f, 0xac, 0x18, 0xb0, 0xbf, 0x5e, 0x84, 0x47, 0x3b, 0x6c, 0x7b, 0x7e, 0xd6, 0x1b, 0x73, - 0xa0, 0x9d, 0xf5, 0xa9, 0x79, 0xa8, 0xc0, 0xa9, 0xad, 0x76, 0xa3, 0xb1, 0xcf, 0x3c, 0x53, 0x48, - 0x5d, 0x62, 0x08, 0x9e, 0x52, 0x0a, 0x47, 0x4e, 0xad, 0x64, 0xe0, 0xe0, 0xcc, 0x9a, 0xf4, 0x89, - 0x45, 0x6f, 0x92, 0x7d, 0x45, 0x2a, 0xf1, 0xc4, 0xc2, 0x3a, 0x10, 0x9b, 0xb8, 0xe8, 0x0a, 0x4c, - 0x3a, 0x7b, 0x8e, 0xcb, 0xe3, 0x66, 0x4b, 0x02, 0xfc, 0x8d, 0xa5, 0xe4, 0xb9, 0x0b, 0x49, 0x04, - 0x9c, 0xae, 0x83, 0xde, 0x00, 0xe4, 0x6f, 0x32, 0xfb, 0xf5, 0xfa, 0x15, 0xe2, 0x09, 0x65, 0x30, - 0x9b, 0xbb, 0x62, 0x7c, 0x24, 0xdc, 0x48, 0x61, 0xe0, 0x8c, 0x5a, 0x89, 0xf8, 0x46, 0x03, 0xf9, - 0xf1, 0x8d, 0x3a, 0x9f, 0x8b, 0x5d, 0x33, 0xf8, 0xfc, 0x5b, 0x8b, 0x5e, 0x5f, 0x9c, 0xc9, 0x37, - 0x23, 0x81, 0xbe, 0xc6, 0x6c, 0x40, 0xb9, 0xac, 0x57, 0x8b, 0x06, 0x73, 0x5a, 0xb3, 0x01, 0x8d, - 0x81, 0xd8, 0xc4, 0xe5, 0x0b, 0x22, 0x8c, 0x9d, 0x90, 0x0d, 0x16, 0x5f, 0x84, 0x2b, 0x53, 0x18, - 0xe8, 0xe3, 0x30, 0x58, 0x77, 0xf7, 0xdc, 0x50, 0x48, 0xba, 0x8e, 0xac, 0x56, 0x8a, 0xcf, 0xc1, - 0x32, 0x27, 0x83, 0x25, 0x3d, 0xfb, 0x47, 0x0a, 0x30, 0x2a, 0x5b, 0x7c, 0xb3, 0xed, 0x47, 0xce, - 0x09, 0x5c, 0xcb, 0x57, 0x8c, 0x6b, 0xf9, 0xa9, 0x4e, 0x31, 0xdb, 0x58, 0x97, 0x72, 0xaf, 0xe3, - 0x1b, 0x89, 0xeb, 0xf8, 0xe9, 0xee, 0xa4, 0x3a, 0x5f, 0xc3, 0x7f, 0xcf, 0x82, 0x49, 0x03, 0xff, - 0x04, 0x6e, 0x83, 0x15, 0xf3, 0x36, 0x78, 0xbc, 0xeb, 0x37, 0xe4, 0xdc, 0x02, 0xdf, 0x5f, 0x4c, - 0xf4, 0x9d, 0x9d, 0xfe, 0x6f, 0x43, 0xdf, 0x8e, 0x13, 0xd4, 0x3b, 0xe5, 0xa8, 0x48, 0x55, 0x9a, - 0xbb, 0xea, 0x04, 0x42, 0x1b, 0xfe, 0x9c, 0x1c, 0x75, 0x5a, 0xd4, 0x55, 0x13, 0xce, 0x9a, 0x42, - 0xaf, 0xc0, 0x40, 0x58, 0xf3, 0x5b, 0xca, 0x2f, 0xe5, 0x02, 0x1b, 0x68, 0x56, 0x72, 0x78, 0x30, - 0x8b, 0xcc, 0xe6, 0x68, 0x31, 0x16, 0xf8, 0xe8, 0x13, 0x30, 0xca, 0x7e, 0x29, 0xd3, 0xb4, 0x62, - 0xbe, 0x38, 0xa2, 0xaa, 0x23, 0x72, 0xbb, 0x4d, 0xa3, 0x08, 0x9b, 0xa4, 0x66, 0xb6, 0xa1, 0xa4, - 0x3e, 0xeb, 0xa1, 0xea, 0x6d, 0xff, 0x75, 0x11, 0xa6, 0x32, 0xd6, 0x1c, 0x0a, 0x8d, 0x99, 0xb8, - 0xdc, 0xe3, 0x52, 0x7d, 0x87, 0x73, 0x11, 0xb2, 0xd7, 0x50, 0x5d, 0xac, 0xad, 0x9e, 0x1b, 0xbd, - 0x19, 0x92, 0x64, 0xa3, 0xb4, 0xa8, 0x7b, 0xa3, 0xb4, 0xb1, 0x13, 0x1b, 0x6a, 0xda, 0x90, 0xea, - 0xe9, 0x43, 0x9d, 0xd3, 0x3f, 0x2d, 0xc2, 0xa9, 0xac, 0x30, 0x92, 0xe8, 0xb3, 0x89, 0x0c, 0xa9, - 0x2f, 0xf5, 0x1a, 0x80, 0x92, 0xa7, 0x4d, 0x15, 0xe1, 0xed, 0xe6, 0xcc, 0x9c, 0xa9, 0x5d, 0x87, - 0x59, 0xb4, 0xc9, 0x02, 0x6c, 0x04, 0x3c, 0xb3, 0xad, 0x3c, 0x3e, 0x3e, 0xd8, 0x73, 0x07, 0x44, - 0x4a, 0xdc, 0x30, 0x61, 0xf6, 0x22, 0x8b, 0xbb, 0x9b, 0xbd, 0xc8, 0x96, 0x67, 0x5c, 0x18, 0xd6, - 0xbe, 0xe6, 0xa1, 0xce, 0xf8, 0x2e, 0xbd, 0xad, 0xb4, 0x7e, 0x3f, 0xd4, 0x59, 0xff, 0x71, 0x0b, - 0x12, 0x9e, 0x10, 0x4a, 0x2c, 0x66, 0xe5, 0x8a, 0xc5, 0x2e, 0x40, 0x5f, 0xe0, 0x37, 0x48, 0x32, - 0x95, 0x28, 0xf6, 0x1b, 0x04, 0x33, 0x08, 0xc5, 0x88, 0x62, 0x61, 0xc7, 0x88, 0xfe, 0x90, 0x13, - 0x4f, 0xb4, 0x27, 0xa0, 0xbf, 0x41, 0xf6, 0x48, 0x23, 0x99, 0xf1, 0xe9, 0x3a, 0x2d, 0xc4, 0x1c, - 0x66, 0xff, 0x42, 0x1f, 0x9c, 0xeb, 0x18, 0xa2, 0x86, 0x3e, 0x87, 0xb6, 0x9d, 0x88, 0xdc, 0x71, - 0xf6, 0x93, 0xa9, 0x59, 0xae, 0xf0, 0x62, 0x2c, 0xe1, 0xcc, 0x2f, 0x8e, 0x47, 0x58, 0x4f, 0x08, - 0x11, 0x45, 0x60, 0x75, 0x01, 0x35, 0x85, 0x52, 0xc5, 0xe3, 0x10, 0x4a, 0xbd, 0x00, 0x10, 0x86, - 0x0d, 0x6e, 0x2f, 0x56, 0x17, 0x0e, 0x77, 0x71, 0x24, 0xfe, 0xea, 0x75, 0x01, 0xc1, 0x1a, 0x16, - 0x2a, 0xc3, 0x44, 0x2b, 0xf0, 0x23, 0x2e, 0x93, 0x2d, 0x73, 0x93, 0xca, 0x7e, 0x33, 0x3a, 0x48, - 0x25, 0x01, 0xc7, 0xa9, 0x1a, 0xe8, 0x65, 0x18, 0x16, 0x11, 0x43, 0x2a, 0xbe, 0xdf, 0x10, 0x62, - 0x20, 0x65, 0x65, 0x58, 0x8d, 0x41, 0x58, 0xc7, 0xd3, 0xaa, 0x31, 0x41, 0xef, 0x60, 0x66, 0x35, - 0x2e, 0xec, 0xd5, 0xf0, 0x12, 0x21, 0x65, 0x87, 0x7a, 0x0a, 0x29, 0x1b, 0x0b, 0xc6, 0x4a, 0x3d, - 0xeb, 0x1d, 0xa1, 0xab, 0x28, 0xe9, 0x2b, 0x7d, 0x30, 0x25, 0x16, 0xce, 0xc3, 0x5e, 0x2e, 0x37, - 0xd3, 0xcb, 0xe5, 0x38, 0x44, 0x67, 0xef, 0xad, 0x99, 0x93, 0x5e, 0x33, 0x3f, 0x6a, 0x81, 0xc9, - 0x5e, 0xa1, 0xff, 0x2b, 0x37, 0xb7, 0xd5, 0xcb, 0xb9, 0xec, 0x9a, 0x8a, 0x51, 0xfa, 0x0e, 0xb3, - 0x5c, 0xd9, 0xff, 0xc6, 0x82, 0xc7, 0xbb, 0x52, 0x44, 0xcb, 0x50, 0x62, 0x3c, 0xa0, 0xf6, 0x3a, - 0x7b, 0x5a, 0x99, 0x5c, 0x4b, 0x40, 0x0e, 0x4b, 0x1a, 0xd7, 0x44, 0xcb, 0xa9, 0x24, 0x62, 0xcf, - 0x64, 0x24, 0x11, 0x3b, 0x6d, 0x0c, 0xcf, 0x03, 0x66, 0x11, 0xfb, 0x61, 0x7a, 0xe3, 0x18, 0xee, - 0x4e, 0xe8, 0x83, 0x86, 0xd8, 0xcf, 0x4e, 0x88, 0xfd, 0x90, 0x89, 0xad, 0xdd, 0x21, 0x1f, 0x85, - 0x09, 0x16, 0x4a, 0x8c, 0x39, 0x00, 0x08, 0x47, 0xac, 0x42, 0x6c, 0xe4, 0x7b, 0x3d, 0x01, 0xc3, - 0x29, 0x6c, 0xfb, 0x0f, 0x8b, 0x30, 0xc0, 0xb7, 0xdf, 0x09, 0xbc, 0x09, 0x9f, 0x85, 0x92, 0xdb, - 0x6c, 0xb6, 0x79, 0x5e, 0xa8, 0xfe, 0xd8, 0x64, 0x74, 0x55, 0x16, 0xe2, 0x18, 0x8e, 0x56, 0x84, - 0xc4, 0xb9, 0x43, 0xb4, 0x52, 0xde, 0xf1, 0xb9, 0xb2, 0x13, 0x39, 0x9c, 0xc1, 0x51, 0xf7, 0x6c, - 0x2c, 0x9b, 0x46, 0x9f, 0x02, 0x08, 0xa3, 0xc0, 0xf5, 0xb6, 0x69, 0x99, 0x08, 0x92, 0xfc, 0xfe, - 0x0e, 0xd4, 0xaa, 0x0a, 0x99, 0xd3, 0x8c, 0xcf, 0x1c, 0x05, 0xc0, 0x1a, 0x45, 0x34, 0x67, 0xdc, - 0xf4, 0x33, 0x89, 0xb9, 0x03, 0x4e, 0x35, 0x9e, 0xb3, 0x99, 0x0f, 0x41, 0x49, 0x11, 0xef, 0x26, - 0x7f, 0x1a, 0xd1, 0xd9, 0xa2, 0x8f, 0xc0, 0x78, 0xa2, 0x6f, 0x47, 0x12, 0x5f, 0xfd, 0xa2, 0x05, - 0xe3, 0xbc, 0x33, 0xcb, 0xde, 0x9e, 0xb8, 0x0d, 0xee, 0xc1, 0xa9, 0x46, 0xc6, 0xa9, 0x2c, 0xa6, - 0xbf, 0xf7, 0x53, 0x5c, 0x89, 0xab, 0xb2, 0xa0, 0x38, 0xb3, 0x0d, 0x74, 0x89, 0xee, 0x38, 0x7a, - 0xea, 0x3a, 0x0d, 0xe1, 0xf8, 0x3d, 0xc2, 0x77, 0x1b, 0x2f, 0xc3, 0x0a, 0x6a, 0xff, 0x8e, 0x05, - 0x93, 0xbc, 0xe7, 0xd7, 0xc8, 0xbe, 0x3a, 0x9b, 0xbe, 0x99, 0x7d, 0x17, 0x19, 0x09, 0x0b, 0x39, - 0x19, 0x09, 0xf5, 0x4f, 0x2b, 0x76, 0xfc, 0xb4, 0x2f, 0x5b, 0x20, 0x56, 0xc8, 0x09, 0x08, 0x21, - 0xbe, 0xd3, 0x14, 0x42, 0xcc, 0xe4, 0x6f, 0x82, 0x1c, 0xe9, 0xc3, 0x9f, 0x59, 0x30, 0xc1, 0x11, - 0x62, 0x6d, 0xf9, 0x37, 0x75, 0x1e, 0x7a, 0xc9, 0x5b, 0x7e, 0x8d, 0xec, 0x6f, 0xf8, 0x15, 0x27, - 0xda, 0xc9, 0xfe, 0x28, 0x63, 0xb2, 0xfa, 0x3a, 0x4e, 0x56, 0x5d, 0x6e, 0x20, 0x23, 0x61, 0x4f, - 0x97, 0x68, 0x18, 0x47, 0x4d, 0xd8, 0x63, 0x7f, 0xc3, 0x02, 0xc4, 0x9b, 0x31, 0x18, 0x37, 0xca, - 0x0e, 0xb1, 0x52, 0xed, 0xa2, 0x8b, 0x8f, 0x26, 0x05, 0xc1, 0x1a, 0xd6, 0xb1, 0x0c, 0x4f, 0xc2, - 0xe4, 0xa1, 0xd8, 0xdd, 0xe4, 0xe1, 0x08, 0x23, 0xfa, 0xcf, 0x07, 0x20, 0xe9, 0xf2, 0x85, 0x6e, - 0xc1, 0x48, 0xcd, 0x69, 0x39, 0x9b, 0x6e, 0xc3, 0x8d, 0x5c, 0x12, 0x76, 0xb2, 0x87, 0x5a, 0xd2, - 0xf0, 0x84, 0x92, 0x5a, 0x2b, 0xc1, 0x06, 0x1d, 0x34, 0x07, 0xd0, 0x0a, 0xdc, 0x3d, 0xb7, 0x41, - 0xb6, 0x99, 0xac, 0x84, 0x85, 0x9a, 0xe0, 0xc6, 0x59, 0xb2, 0x14, 0x6b, 0x18, 0x19, 0xfe, 0xf5, - 0xc5, 0x87, 0xec, 0x5f, 0x0f, 0x27, 0xe6, 0x5f, 0xdf, 0x77, 0x24, 0xff, 0xfa, 0xa1, 0x23, 0xfb, - 0xd7, 0xf7, 0xf7, 0xe4, 0x5f, 0x8f, 0xe1, 0x8c, 0xe4, 0x3d, 0xe9, 0xff, 0x15, 0xb7, 0x41, 0xc4, - 0x83, 0x83, 0xc7, 0xc7, 0x98, 0xb9, 0x7f, 0x30, 0x7b, 0x06, 0x67, 0x62, 0xe0, 0x9c, 0x9a, 0xe8, - 0x63, 0x30, 0xed, 0x34, 0x1a, 0xfe, 0x1d, 0x35, 0xa9, 0xcb, 0x61, 0xcd, 0x69, 0x70, 0x25, 0xc4, - 0x20, 0xa3, 0xfa, 0xd8, 0xfd, 0x83, 0xd9, 0xe9, 0x85, 0x1c, 0x1c, 0x9c, 0x5b, 0x1b, 0x7d, 0x18, - 0x4a, 0xad, 0xc0, 0xaf, 0xad, 0x69, 0x7e, 0xa9, 0xe7, 0xe9, 0x00, 0x56, 0x64, 0xe1, 0xe1, 0xc1, - 0xec, 0xa8, 0xfa, 0xc3, 0x2e, 0xfc, 0xb8, 0x42, 0x86, 0xc3, 0xfc, 0xf0, 0xb1, 0x3a, 0xcc, 0xef, - 0xc2, 0x54, 0x95, 0x04, 0xae, 0xd3, 0x70, 0xef, 0x51, 0x7e, 0x59, 0x9e, 0x4f, 0x1b, 0x50, 0x0a, - 0x12, 0x27, 0x72, 0x4f, 0x11, 0x44, 0xb5, 0xcc, 0x29, 0xf2, 0x04, 0x8e, 0x09, 0xd9, 0xff, 0xc3, - 0x82, 0x41, 0xe1, 0xe2, 0x75, 0x02, 0x5c, 0xe3, 0x82, 0xa1, 0x49, 0x98, 0xcd, 0x1e, 0x30, 0xd6, - 0x99, 0x5c, 0x1d, 0xc2, 0x6a, 0x42, 0x87, 0xf0, 0x78, 0x27, 0x22, 0x9d, 0xb5, 0x07, 0x7f, 0xb9, - 0x48, 0xb9, 0x77, 0xc3, 0xd9, 0xf8, 0xe1, 0x0f, 0xc1, 0x3a, 0x0c, 0x86, 0xc2, 0xd9, 0xb5, 0x90, - 0xef, 0xd3, 0x90, 0x9c, 0xc4, 0xd8, 0x8e, 0x4d, 0xb8, 0xb7, 0x4a, 0x22, 0x99, 0x5e, 0xb4, 0xc5, - 0x87, 0xe8, 0x45, 0xdb, 0xcd, 0x1d, 0xbb, 0xef, 0x38, 0xdc, 0xb1, 0xed, 0xaf, 0xb1, 0x9b, 0x53, - 0x2f, 0x3f, 0x01, 0xa6, 0xea, 0x8a, 0x79, 0xc7, 0xda, 0x1d, 0x56, 0x96, 0xe8, 0x54, 0x0e, 0x73, - 0xf5, 0xf3, 0x16, 0x9c, 0xcb, 0xf8, 0x2a, 0x8d, 0xd3, 0x7a, 0x0e, 0x86, 0x9c, 0x76, 0xdd, 0x55, - 0x7b, 0x59, 0xd3, 0x27, 0x2e, 0x88, 0x72, 0xac, 0x30, 0xd0, 0x12, 0x4c, 0x92, 0xbb, 0x2d, 0x97, - 0xab, 0x52, 0x75, 0xf3, 0xdf, 0x22, 0xf7, 0x0b, 0x5c, 0x4e, 0x02, 0x71, 0x1a, 0x5f, 0x45, 0xce, - 0x29, 0xe6, 0x46, 0xce, 0xf9, 0x9b, 0x16, 0x0c, 0x2b, 0x77, 0xcf, 0x87, 0x3e, 0xda, 0x1f, 0x35, - 0x47, 0xfb, 0xd1, 0x0e, 0xa3, 0x9d, 0x33, 0xcc, 0xbf, 0x55, 0x50, 0xfd, 0xad, 0xf8, 0x41, 0xd4, - 0x03, 0x07, 0xf7, 0xe0, 0xae, 0x0b, 0x97, 0x61, 0xd8, 0x69, 0xb5, 0x24, 0x40, 0xda, 0xa0, 0xb1, - 0x78, 0xd0, 0x71, 0x31, 0xd6, 0x71, 0x94, 0x27, 0x45, 0x31, 0xd7, 0x93, 0xa2, 0x0e, 0x10, 0x39, - 0xc1, 0x36, 0x89, 0x68, 0x99, 0x30, 0x99, 0xcd, 0x3f, 0x6f, 0xda, 0x91, 0xdb, 0x98, 0x73, 0xbd, - 0x28, 0x8c, 0x82, 0xb9, 0x55, 0x2f, 0xba, 0x11, 0xf0, 0x27, 0xa4, 0x16, 0x7b, 0x4a, 0xd1, 0xc2, - 0x1a, 0x5d, 0x19, 0xda, 0x80, 0xb5, 0xd1, 0x6f, 0x1a, 0x33, 0xac, 0x8b, 0x72, 0xac, 0x30, 0xec, - 0x0f, 0xb1, 0xdb, 0x87, 0x8d, 0xe9, 0xd1, 0xe2, 0x2e, 0x7d, 0x79, 0x44, 0xcd, 0x06, 0xd3, 0x64, - 0x96, 0xf5, 0xe8, 0x4e, 0x9d, 0x0f, 0x7b, 0xda, 0xb0, 0xee, 0xd7, 0x17, 0x87, 0x80, 0x42, 0xdf, - 0x95, 0x32, 0x50, 0x79, 0xbe, 0xcb, 0xad, 0x71, 0x04, 0x93, 0x14, 0x96, 0x1c, 0x86, 0xa5, 0xce, - 0x58, 0xad, 0x88, 0x7d, 0xa1, 0x25, 0x87, 0x11, 0x00, 0x1c, 0xe3, 0x50, 0x66, 0x4a, 0xfd, 0x09, - 0xa7, 0x51, 0x1c, 0x24, 0x55, 0x61, 0x87, 0x58, 0xc3, 0x40, 0xf3, 0x42, 0xa0, 0xc0, 0xf5, 0x02, - 0x8f, 0x26, 0x04, 0x0a, 0x72, 0xb8, 0x34, 0x29, 0xd0, 0x65, 0x18, 0x56, 0xa9, 0xc0, 0x2b, 0x3c, - 0x2d, 0x93, 0x58, 0x66, 0xcb, 0x71, 0x31, 0xd6, 0x71, 0xd0, 0x06, 0x8c, 0x87, 0x5c, 0xce, 0xa6, - 0x22, 0x57, 0x73, 0x79, 0xe5, 0xfb, 0x95, 0xa3, 0xad, 0x09, 0x3e, 0x64, 0x45, 0xfc, 0x74, 0x92, - 0xe1, 0x07, 0x92, 0x24, 0xd0, 0xeb, 0x30, 0xd6, 0xf0, 0x9d, 0xfa, 0xa2, 0xd3, 0x70, 0xbc, 0x1a, - 0x1b, 0x9f, 0x21, 0x33, 0xa3, 0xec, 0x75, 0x03, 0x8a, 0x13, 0xd8, 0x94, 0x79, 0xd3, 0x4b, 0x44, - 0xb4, 0x75, 0xc7, 0xdb, 0x26, 0xa1, 0x48, 0xec, 0xcc, 0x98, 0xb7, 0xeb, 0x39, 0x38, 0x38, 0xb7, - 0x36, 0x7a, 0x05, 0x46, 0xe4, 0xe7, 0x6b, 0xd1, 0x3a, 0x62, 0xa7, 0x14, 0x0d, 0x86, 0x0d, 0x4c, - 0x74, 0x07, 0x4e, 0xcb, 0xff, 0x1b, 0x81, 0xb3, 0xb5, 0xe5, 0xd6, 0x84, 0x0b, 0x3b, 0xf7, 0x5e, - 0x5d, 0x90, 0x2e, 0x96, 0xcb, 0x59, 0x48, 0x87, 0x07, 0xb3, 0x17, 0xc4, 0xa8, 0x65, 0xc2, 0xd9, - 0x24, 0x66, 0xd3, 0x47, 0x6b, 0x30, 0xb5, 0x43, 0x9c, 0x46, 0xb4, 0xb3, 0xb4, 0x43, 0x6a, 0xbb, - 0x72, 0xd3, 0xb1, 0x18, 0x20, 0x9a, 0x03, 0xc7, 0xd5, 0x34, 0x0a, 0xce, 0xaa, 0x87, 0xde, 0x82, - 0xe9, 0x56, 0x7b, 0xb3, 0xe1, 0x86, 0x3b, 0xeb, 0x7e, 0xc4, 0x4c, 0x81, 0x54, 0x66, 0x71, 0x11, - 0x2c, 0x44, 0x45, 0x59, 0xa9, 0xe4, 0xe0, 0xe1, 0x5c, 0x0a, 0xe8, 0x1e, 0x9c, 0x4e, 0x2c, 0x06, - 0x11, 0x2e, 0x61, 0x2c, 0x3f, 0x77, 0x45, 0x35, 0xab, 0x82, 0x88, 0x3c, 0x92, 0x05, 0xc2, 0xd9, - 0x4d, 0xa0, 0x57, 0x01, 0xdc, 0xd6, 0x8a, 0xd3, 0x74, 0x1b, 0xf4, 0xb9, 0x38, 0xc5, 0xd6, 0x09, - 0x7d, 0x3a, 0xc0, 0x6a, 0x45, 0x96, 0xd2, 0xf3, 0x59, 0xfc, 0xdb, 0xc7, 0x1a, 0x36, 0xba, 0x0e, - 0x63, 0xe2, 0xdf, 0xbe, 0x98, 0x56, 0x1e, 0xb5, 0xe3, 0x49, 0x16, 0x72, 0xa9, 0xa2, 0x43, 0x0e, - 0x53, 0x25, 0x38, 0x51, 0x17, 0x6d, 0xc3, 0x39, 0x99, 0x87, 0x4c, 0x5f, 0xa3, 0x72, 0x0e, 0x42, - 0x96, 0x30, 0x62, 0x88, 0xfb, 0x86, 0x2c, 0x74, 0x42, 0xc4, 0x9d, 0xe9, 0xd0, 0xbb, 0x5d, 0x5f, - 0xea, 0xdc, 0x7b, 0xf6, 0x34, 0x37, 0x4d, 0xa2, 0x77, 0xfb, 0xf5, 0x24, 0x10, 0xa7, 0xf1, 0x51, - 0x08, 0xa7, 0x5d, 0x2f, 0x6b, 0x65, 0x9f, 0x61, 0x84, 0x3e, 0xc2, 0x1d, 0x87, 0x3b, 0xaf, 0xea, - 0x4c, 0x38, 0x5f, 0xd5, 0x99, 0xb4, 0xdf, 0x99, 0x05, 0xde, 0x6f, 0x5b, 0xb4, 0xb6, 0xc6, 0xa5, - 0xa3, 0x4f, 0xc3, 0x88, 0xfe, 0x61, 0x82, 0xe3, 0xb8, 0x98, 0xcd, 0xc4, 0x6a, 0x67, 0x03, 0xe7, - 0xf1, 0xd5, 0xfe, 0xd7, 0x61, 0xd8, 0xa0, 0x88, 0x6a, 0x19, 0x2e, 0xf6, 0xf3, 0xbd, 0x71, 0x34, - 0xbd, 0x1b, 0xa0, 0x11, 0xc8, 0x5e, 0xf2, 0xe8, 0x3a, 0x0c, 0xd5, 0x1a, 0x2e, 0xf1, 0xa2, 0xd5, - 0x4a, 0xa7, 0xf0, 0x7e, 0x4b, 0x02, 0x47, 0xec, 0x21, 0x91, 0xff, 0x81, 0x97, 0x61, 0x45, 0xc1, - 0xfe, 0xb5, 0x02, 0xcc, 0x76, 0x49, 0x26, 0x92, 0x50, 0x47, 0x59, 0x3d, 0xa9, 0xa3, 0x16, 0x64, - 0xea, 0xfc, 0xf5, 0x84, 0xa4, 0x2b, 0x91, 0x16, 0x3f, 0x96, 0x77, 0x25, 0xf1, 0x7b, 0x76, 0x0f, - 0xd0, 0x35, 0x5a, 0x7d, 0x5d, 0x1d, 0x5c, 0x0c, 0x4d, 0x76, 0x7f, 0xef, 0xcf, 0xdf, 0x5c, 0xad, - 0xa4, 0xfd, 0xb5, 0x02, 0x9c, 0x56, 0x43, 0xf8, 0xed, 0x3b, 0x70, 0x37, 0xd3, 0x03, 0x77, 0x0c, - 0x3a, 0x5d, 0xfb, 0x06, 0x0c, 0xf0, 0x78, 0x85, 0x3d, 0xb0, 0xdd, 0x4f, 0x98, 0x61, 0x84, 0x15, - 0xa7, 0x67, 0x84, 0x12, 0xfe, 0x41, 0x0b, 0xc6, 0x13, 0x7e, 0x66, 0x08, 0x6b, 0xce, 0xc8, 0x0f, - 0xc2, 0x1a, 0x67, 0x31, 0xdd, 0x17, 0xa0, 0x6f, 0xc7, 0x0f, 0xa3, 0xa4, 0xc1, 0xc7, 0x55, 0x3f, - 0x8c, 0x30, 0x83, 0xd8, 0xbf, 0x6b, 0x41, 0xff, 0x86, 0xe3, 0x7a, 0x91, 0x54, 0x0e, 0x58, 0x39, - 0xca, 0x81, 0x5e, 0xbe, 0x0b, 0xbd, 0x0c, 0x03, 0x64, 0x6b, 0x8b, 0xd4, 0x22, 0x31, 0xab, 0x32, - 0x92, 0xc3, 0xc0, 0x32, 0x2b, 0xa5, 0x7c, 0x20, 0x6b, 0x8c, 0xff, 0xc5, 0x02, 0x19, 0xdd, 0x86, - 0x52, 0xe4, 0x36, 0xc9, 0x42, 0xbd, 0x2e, 0x54, 0xe6, 0x0f, 0x10, 0x8d, 0x62, 0x43, 0x12, 0xc0, - 0x31, 0x2d, 0xfb, 0x0b, 0x05, 0x80, 0x38, 0xd0, 0x53, 0xb7, 0x4f, 0x5c, 0x4c, 0x29, 0x53, 0x2f, - 0x66, 0x28, 0x53, 0x51, 0x4c, 0x30, 0x43, 0x93, 0xaa, 0x86, 0xa9, 0xd8, 0xd3, 0x30, 0xf5, 0x1d, - 0x65, 0x98, 0x96, 0x60, 0x32, 0x0e, 0x54, 0x65, 0xc6, 0xe9, 0x63, 0xd7, 0xe7, 0x46, 0x12, 0x88, - 0xd3, 0xf8, 0x36, 0x81, 0x0b, 0x2a, 0x5e, 0x8f, 0xb8, 0xd1, 0x98, 0x45, 0xb6, 0xae, 0x9c, 0xee, - 0x32, 0x4e, 0xb1, 0xb6, 0xb8, 0x90, 0xab, 0x2d, 0xfe, 0x29, 0x0b, 0x4e, 0x25, 0xdb, 0x61, 0xee, - 0xcb, 0x9f, 0xb7, 0xe0, 0x34, 0xd3, 0x99, 0xb3, 0x56, 0xd3, 0x1a, 0xfa, 0x97, 0x3a, 0xc6, 0x20, - 0xca, 0xe9, 0x71, 0x1c, 0x32, 0x64, 0x2d, 0x8b, 0x34, 0xce, 0x6e, 0xd1, 0xfe, 0xef, 0x7d, 0x30, - 0x9d, 0x17, 0xbc, 0x88, 0x39, 0x6c, 0x38, 0x77, 0xab, 0xbb, 0xe4, 0x8e, 0x30, 0x8b, 0x8f, 0x1d, - 0x36, 0x78, 0x31, 0x96, 0xf0, 0x64, 0x7e, 0x88, 0x42, 0x8f, 0xf9, 0x21, 0x76, 0x60, 0xf2, 0xce, - 0x0e, 0xf1, 0x6e, 0x7a, 0xa1, 0x13, 0xb9, 0xe1, 0x96, 0xcb, 0xf4, 0xcb, 0x7c, 0xdd, 0xc8, 0xa4, - 0xb2, 0x93, 0xb7, 0x93, 0x08, 0x87, 0x07, 0xb3, 0xe7, 0x8c, 0x82, 0xb8, 0xcb, 0xfc, 0x20, 0xc1, - 0x69, 0xa2, 0xe9, 0xf4, 0x1a, 0x7d, 0x0f, 0x39, 0xbd, 0x46, 0xd3, 0x15, 0x56, 0x29, 0xd2, 0x1a, - 0x9f, 0xbd, 0x1c, 0xd7, 0x54, 0x29, 0xd6, 0x30, 0xd0, 0x27, 0x01, 0xe9, 0xe9, 0x83, 0x8c, 0xd8, - 0x91, 0xcf, 0xdf, 0x3f, 0x98, 0x45, 0xeb, 0x29, 0xe8, 0xe1, 0xc1, 0xec, 0x14, 0x2d, 0x5d, 0xf5, - 0xe8, 0x0b, 0x34, 0x0e, 0xb8, 0x95, 0x41, 0x08, 0xdd, 0x86, 0x09, 0x5a, 0xca, 0x76, 0x94, 0x0c, - 0x4c, 0xc9, 0x5f, 0x8d, 0xcf, 0xde, 0x3f, 0x98, 0x9d, 0x58, 0x4f, 0xc0, 0xf2, 0x48, 0xa7, 0x88, - 0xa0, 0x57, 0x61, 0x2c, 0x5e, 0x57, 0xd7, 0xc8, 0x3e, 0x0f, 0x37, 0x53, 0xe2, 0x82, 0xef, 0x35, - 0x03, 0x82, 0x13, 0x98, 0xf6, 0xe7, 0x2d, 0x38, 0x9b, 0x9b, 0xe2, 0x1a, 0x5d, 0x82, 0x21, 0xa7, - 0xe5, 0x72, 0x35, 0x86, 0xb8, 0x6a, 0x98, 0xb8, 0xac, 0xb2, 0xca, 0x95, 0x18, 0x0a, 0x4a, 0x4f, - 0xf8, 0x5d, 0xd7, 0xab, 0x27, 0x4f, 0xf8, 0x6b, 0xae, 0x57, 0xc7, 0x0c, 0xa2, 0xae, 0xac, 0x62, - 0x6e, 0xa4, 0xe6, 0xaf, 0xd0, 0xbd, 0x9a, 0x91, 0x0c, 0xfb, 0x64, 0xbb, 0x81, 0x9e, 0xd5, 0x55, - 0x8e, 0xc2, 0xba, 0x30, 0x57, 0xdd, 0xf8, 0x03, 0x16, 0x08, 0x27, 0xe2, 0x1e, 0xee, 0xe4, 0x4f, - 0xc0, 0xc8, 0x5e, 0x3a, 0xb5, 0xda, 0x85, 0x7c, 0xaf, 0x6a, 0x91, 0x50, 0x4d, 0x31, 0xda, 0x46, - 0x1a, 0x35, 0x83, 0x96, 0x5d, 0x07, 0x01, 0x2d, 0x13, 0xa6, 0x58, 0xe8, 0xde, 0x9b, 0x17, 0x00, - 0xea, 0x0c, 0x97, 0xe5, 0x5b, 0x2d, 0x98, 0x1c, 0x57, 0x59, 0x41, 0xb0, 0x86, 0x65, 0xff, 0xcb, - 0x02, 0x0c, 0xcb, 0x54, 0x5e, 0x6d, 0xaf, 0x17, 0xf1, 0xdf, 0x91, 0x72, 0xfb, 0xa2, 0x79, 0x28, - 0x31, 0xf9, 0x74, 0x25, 0x96, 0x9a, 0x2a, 0xe9, 0xd0, 0x9a, 0x04, 0xe0, 0x18, 0x87, 0x9e, 0x8e, - 0x61, 0x7b, 0x93, 0xa1, 0x27, 0x5c, 0x5e, 0xab, 0xbc, 0x18, 0x4b, 0x38, 0xfa, 0x18, 0x4c, 0xf0, - 0x7a, 0x81, 0xdf, 0x72, 0xb6, 0xb9, 0x4e, 0xab, 0x5f, 0xc5, 0x11, 0x99, 0x58, 0x4b, 0xc0, 0x0e, - 0x0f, 0x66, 0x4f, 0x25, 0xcb, 0x98, 0xb2, 0x36, 0x45, 0x85, 0x99, 0xae, 0xf1, 0x46, 0xe8, 0xa9, - 0x9e, 0xb2, 0x78, 0x8b, 0x41, 0x58, 0xc7, 0xb3, 0x3f, 0x0d, 0x28, 0x9d, 0xd4, 0x0c, 0xbd, 0xc1, - 0xed, 0x95, 0xdd, 0x80, 0xd4, 0x3b, 0x29, 0x6f, 0xf5, 0x68, 0x19, 0xd2, 0x5b, 0x8d, 0xd7, 0xc2, - 0xaa, 0xbe, 0xfd, 0xff, 0x15, 0x61, 0x22, 0xe9, 0x9f, 0x8f, 0xae, 0xc2, 0x00, 0x67, 0x29, 0x05, - 0xf9, 0x0e, 0xb6, 0x41, 0x9a, 0x57, 0x3f, 0xbb, 0x5c, 0x05, 0x57, 0x2a, 0xea, 0xa3, 0xb7, 0x60, - 0xb8, 0xee, 0xdf, 0xf1, 0xee, 0x38, 0x41, 0x7d, 0xa1, 0xb2, 0x2a, 0x96, 0x73, 0xa6, 0xb0, 0xa2, - 0x1c, 0xa3, 0xe9, 0x91, 0x02, 0x98, 0x1e, 0x3c, 0x06, 0x61, 0x9d, 0x1c, 0xda, 0x60, 0x99, 0x10, - 0xb6, 0xdc, 0xed, 0x35, 0xa7, 0xd5, 0xc9, 0x79, 0x65, 0x49, 0x22, 0x69, 0x94, 0x47, 0x45, 0xba, - 0x04, 0x0e, 0xc0, 0x31, 0x21, 0xf4, 0x59, 0x98, 0x0a, 0x73, 0x54, 0x28, 0x79, 0x39, 0x2e, 0x3b, - 0x69, 0x15, 0x16, 0x1f, 0xb9, 0x7f, 0x30, 0x3b, 0x95, 0xa5, 0x6c, 0xc9, 0x6a, 0xc6, 0xfe, 0xe2, - 0x29, 0x30, 0x36, 0xb1, 0x91, 0xf2, 0xd8, 0x3a, 0xa6, 0x94, 0xc7, 0x18, 0x86, 0x48, 0xb3, 0x15, - 0xed, 0x97, 0xdd, 0x40, 0xcc, 0x49, 0x26, 0xcd, 0x65, 0x81, 0x93, 0xa6, 0x29, 0x21, 0x58, 0xd1, - 0xc9, 0xce, 0x4b, 0x5d, 0xfc, 0x26, 0xe6, 0xa5, 0xee, 0x3b, 0xc1, 0xbc, 0xd4, 0xeb, 0x30, 0xb8, - 0xed, 0x46, 0x98, 0xb4, 0x7c, 0xf1, 0x98, 0xcb, 0x5c, 0x87, 0x57, 0x38, 0x4a, 0x3a, 0x03, 0xaa, - 0x00, 0x60, 0x49, 0x04, 0xbd, 0xa1, 0x76, 0xe0, 0x40, 0xbe, 0xc0, 0x25, 0x6d, 0xc4, 0x92, 0xb9, - 0x07, 0x45, 0xf6, 0xe9, 0xc1, 0x07, 0xcd, 0x3e, 0xbd, 0x22, 0x73, 0x46, 0x0f, 0xe5, 0x7b, 0x9a, - 0xb1, 0x94, 0xd0, 0x5d, 0x32, 0x45, 0xdf, 0xd2, 0xf3, 0x6c, 0x97, 0xf2, 0x4f, 0x02, 0x95, 0x42, - 0xbb, 0xc7, 0xec, 0xda, 0x3f, 0x60, 0xc1, 0xe9, 0x56, 0x56, 0xca, 0x79, 0x61, 0xef, 0xf1, 0x72, - 0xcf, 0x59, 0xed, 0x8d, 0x06, 0x99, 0x9c, 0x34, 0x13, 0x0d, 0x67, 0x37, 0x47, 0x07, 0x3a, 0xd8, - 0xac, 0x0b, 0xbb, 0x83, 0x27, 0x72, 0xd2, 0x74, 0x77, 0x48, 0xce, 0xbd, 0x91, 0x91, 0x12, 0xfa, - 0xc9, 0xbc, 0x94, 0xd0, 0x3d, 0x27, 0x82, 0x7e, 0x43, 0x25, 0xe8, 0x1e, 0xcd, 0x5f, 0x4a, 0x3c, - 0xfd, 0x76, 0xd7, 0xb4, 0xdc, 0x6f, 0xa8, 0xb4, 0xdc, 0x1d, 0x42, 0x4f, 0xf3, 0xa4, 0xdb, 0x5d, - 0x93, 0x71, 0x6b, 0x09, 0xb5, 0xc7, 0x8f, 0x27, 0xa1, 0xb6, 0x71, 0xd5, 0xf0, 0x9c, 0xce, 0xcf, - 0x76, 0xb9, 0x6a, 0x0c, 0xba, 0x9d, 0x2f, 0x1b, 0x9e, 0x3c, 0x7c, 0xf2, 0x81, 0x92, 0x87, 0xdf, - 0xd2, 0x93, 0x71, 0xa3, 0x2e, 0xd9, 0xa6, 0x29, 0x52, 0x8f, 0x29, 0xb8, 0x6f, 0xe9, 0x17, 0xe0, - 0x54, 0x3e, 0x5d, 0x75, 0xcf, 0xa5, 0xe9, 0x66, 0x5e, 0x81, 0xa9, 0xd4, 0xde, 0xa7, 0x4e, 0x26, - 0xb5, 0xf7, 0xe9, 0x63, 0x4f, 0xed, 0x7d, 0xe6, 0x04, 0x52, 0x7b, 0x3f, 0x72, 0x82, 0xa9, 0xbd, - 0x6f, 0x31, 0x23, 0x29, 0x1e, 0x8a, 0x49, 0x84, 0xca, 0x7e, 0x26, 0x27, 0x92, 0x59, 0x3a, 0x5e, - 0x13, 0xff, 0x38, 0x05, 0xc2, 0x31, 0xa9, 0x8c, 0x94, 0xe1, 0xd3, 0x0f, 0x21, 0x65, 0xf8, 0x7a, - 0x9c, 0x32, 0xfc, 0x6c, 0xfe, 0x54, 0x67, 0xb8, 0xd5, 0xe4, 0x24, 0x0a, 0xbf, 0xa5, 0x27, 0xf8, - 0x7e, 0xb4, 0x83, 0x26, 0x2c, 0x4b, 0xa0, 0xdc, 0x21, 0xad, 0xf7, 0xeb, 0x3c, 0xad, 0xf7, 0x63, - 0xf9, 0x27, 0x79, 0xf2, 0xba, 0x33, 0x92, 0x79, 0xd3, 0x7e, 0xa9, 0x50, 0xa6, 0x2c, 0x28, 0x78, - 0x4e, 0xbf, 0x54, 0x2c, 0xd4, 0x74, 0xbf, 0x14, 0x08, 0xc7, 0xa4, 0xec, 0x1f, 0x2a, 0xc0, 0xf9, - 0xce, 0xfb, 0x2d, 0x96, 0x92, 0x57, 0x62, 0xc3, 0x80, 0x84, 0x94, 0x9c, 0xbf, 0xd9, 0x62, 0xac, - 0x9e, 0x23, 0x33, 0x5e, 0x81, 0x49, 0xe5, 0x8f, 0xd3, 0x70, 0x6b, 0xfb, 0xeb, 0xf1, 0x33, 0x59, - 0xc5, 0x30, 0xa8, 0x26, 0x11, 0x70, 0xba, 0x0e, 0x5a, 0x80, 0x71, 0xa3, 0x70, 0xb5, 0x2c, 0xde, - 0x66, 0x71, 0x18, 0x6a, 0x13, 0x8c, 0x93, 0xf8, 0xf6, 0x97, 0x2c, 0x78, 0x24, 0x27, 0x27, 0x66, - 0xcf, 0x81, 0x07, 0xb7, 0x60, 0xbc, 0x65, 0x56, 0xed, 0x12, 0x2b, 0xd5, 0xc8, 0xbc, 0xa9, 0xfa, - 0x9a, 0x00, 0xe0, 0x24, 0x51, 0xfb, 0x67, 0x0b, 0x70, 0xae, 0xa3, 0x81, 0x29, 0xc2, 0x70, 0x66, - 0xbb, 0x19, 0x3a, 0x4b, 0x01, 0xa9, 0x13, 0x2f, 0x72, 0x9d, 0x46, 0xb5, 0x45, 0x6a, 0x9a, 0x9e, - 0x83, 0x59, 0x6a, 0x5e, 0x59, 0xab, 0x2e, 0xa4, 0x31, 0x70, 0x4e, 0x4d, 0xb4, 0x02, 0x28, 0x0d, - 0x11, 0x33, 0xcc, 0xc2, 0xcb, 0xa7, 0xe9, 0xe1, 0x8c, 0x1a, 0xe8, 0x43, 0x30, 0xaa, 0x0c, 0x57, - 0xb5, 0x19, 0x67, 0x07, 0x3b, 0xd6, 0x01, 0xd8, 0xc4, 0x43, 0x97, 0x79, 0x7e, 0x02, 0x91, 0xc9, - 0x42, 0x28, 0x45, 0xc6, 0x65, 0xf2, 0x01, 0x51, 0x8c, 0x75, 0x9c, 0xc5, 0x57, 0x7e, 0xfd, 0xf7, - 0xcf, 0xbf, 0xef, 0x37, 0x7f, 0xff, 0xfc, 0xfb, 0x7e, 0xe7, 0xf7, 0xcf, 0xbf, 0xef, 0x7b, 0xee, - 0x9f, 0xb7, 0x7e, 0xfd, 0xfe, 0x79, 0xeb, 0x37, 0xef, 0x9f, 0xb7, 0x7e, 0xe7, 0xfe, 0x79, 0xeb, - 0xf7, 0xee, 0x9f, 0xb7, 0xbe, 0xf0, 0x07, 0xe7, 0xdf, 0xf7, 0x09, 0x14, 0x87, 0xf2, 0x9c, 0xa7, - 0xb3, 0x33, 0xbf, 0x77, 0xf9, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xd1, 0x15, 0x7f, 0x61, 0xe2, - 0x0a, 0x01, 0x00, + // 14547 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x69, 0x8c, 0x24, 0xd7, + 0x79, 0x98, 0xaa, 0x7b, 0xae, 0xfe, 0xe6, 0x7e, 0xb3, 0xbb, 0x9c, 0x1d, 0x72, 0x77, 0x96, 0x45, + 0x72, 0xb9, 0x14, 0xc9, 0x19, 0x2d, 0x0f, 0x89, 0x26, 0x25, 0x5a, 0x73, 0xee, 0x36, 0x77, 0x67, + 0xb6, 0xf9, 0x7a, 0x76, 0x57, 0x07, 0x25, 0xa8, 0xa6, 0xfb, 0xcd, 0x4c, 0x69, 0xba, 0xab, 0x9a, + 0x55, 0xd5, 0xb3, 0x3b, 0x8c, 0x84, 0x38, 0xf2, 0x29, 0xdb, 0x09, 0x84, 0xc0, 0x39, 0x20, 0x1b, + 0x46, 0xe0, 0x38, 0xb6, 0x15, 0xe5, 0x52, 0xe4, 0xd8, 0x8e, 0xe5, 0xd8, 0xce, 0xed, 0x04, 0x81, + 0xe3, 0x18, 0x88, 0x65, 0xc0, 0xc8, 0xc4, 0x5e, 0x07, 0x30, 0x04, 0x24, 0xb6, 0x73, 0x01, 0xc9, + 0xc4, 0x89, 0x83, 0x77, 0xd6, 0x7b, 0x75, 0x74, 0xf7, 0x2c, 0x67, 0x47, 0x94, 0xc0, 0x7f, 0xdd, + 0xdf, 0xf7, 0xbd, 0xef, 0xbd, 0x7a, 0xe7, 0xf7, 0xbe, 0xef, 0x7b, 0xdf, 0x07, 0xaf, 0xec, 0xbe, + 0x14, 0xce, 0xb9, 0xfe, 0xfc, 0x6e, 0x7b, 0x93, 0x04, 0x1e, 0x89, 0x48, 0x38, 0xbf, 0x47, 0xbc, + 0xba, 0x1f, 0xcc, 0x0b, 0x84, 0xd3, 0x72, 0xe7, 0x6b, 0x7e, 0x40, 0xe6, 0xf7, 0x2e, 0xcf, 0x6f, + 0x13, 0x8f, 0x04, 0x4e, 0x44, 0xea, 0x73, 0xad, 0xc0, 0x8f, 0x7c, 0x84, 0x38, 0xcd, 0x9c, 0xd3, + 0x72, 0xe7, 0x28, 0xcd, 0xdc, 0xde, 0xe5, 0x99, 0x67, 0xb7, 0xdd, 0x68, 0xa7, 0xbd, 0x39, 0x57, + 0xf3, 0x9b, 0xf3, 0xdb, 0xfe, 0xb6, 0x3f, 0xcf, 0x48, 0x37, 0xdb, 0x5b, 0xec, 0x1f, 0xfb, 0xc3, + 0x7e, 0x71, 0x16, 0x33, 0x2f, 0xc4, 0xd5, 0x34, 0x9d, 0xda, 0x8e, 0xeb, 0x91, 0x60, 0x7f, 0xbe, + 0xb5, 0xbb, 0xcd, 0xea, 0x0d, 0x48, 0xe8, 0xb7, 0x83, 0x1a, 0x49, 0x56, 0xdc, 0xb1, 0x54, 0x38, + 0xdf, 0x24, 0x91, 0x93, 0xd1, 0xdc, 0x99, 0xf9, 0xbc, 0x52, 0x41, 0xdb, 0x8b, 0xdc, 0x66, 0xba, + 0x9a, 0xf7, 0x77, 0x2b, 0x10, 0xd6, 0x76, 0x48, 0xd3, 0x49, 0x95, 0x7b, 0x3e, 0xaf, 0x5c, 0x3b, + 0x72, 0x1b, 0xf3, 0xae, 0x17, 0x85, 0x51, 0x90, 0x2c, 0x64, 0x7f, 0xdd, 0x82, 0x0b, 0x0b, 0xb7, + 0xab, 0x2b, 0x0d, 0x27, 0x8c, 0xdc, 0xda, 0x62, 0xc3, 0xaf, 0xed, 0x56, 0x23, 0x3f, 0x20, 0xb7, + 0xfc, 0x46, 0xbb, 0x49, 0xaa, 0xac, 0x23, 0xd0, 0x33, 0x30, 0xb4, 0xc7, 0xfe, 0x97, 0x97, 0xa7, + 0xad, 0x0b, 0xd6, 0xa5, 0xd2, 0xe2, 0xc4, 0xaf, 0x1d, 0xcc, 0xbe, 0xe7, 0xde, 0xc1, 0xec, 0xd0, + 0x2d, 0x01, 0xc7, 0x8a, 0x02, 0x5d, 0x84, 0x81, 0xad, 0x70, 0x63, 0xbf, 0x45, 0xa6, 0x0b, 0x8c, + 0x76, 0x4c, 0xd0, 0x0e, 0xac, 0x56, 0x29, 0x14, 0x0b, 0x2c, 0x9a, 0x87, 0x52, 0xcb, 0x09, 0x22, + 0x37, 0x72, 0x7d, 0x6f, 0xba, 0x78, 0xc1, 0xba, 0xd4, 0xbf, 0x38, 0x29, 0x48, 0x4b, 0x15, 0x89, + 0xc0, 0x31, 0x0d, 0x6d, 0x46, 0x40, 0x9c, 0xfa, 0x0d, 0xaf, 0xb1, 0x3f, 0xdd, 0x77, 0xc1, 0xba, + 0x34, 0x14, 0x37, 0x03, 0x0b, 0x38, 0x56, 0x14, 0xf6, 0x17, 0x0b, 0x30, 0xb4, 0xb0, 0xb5, 0xe5, + 0x7a, 0x6e, 0xb4, 0x8f, 0x6e, 0xc1, 0x88, 0xe7, 0xd7, 0x89, 0xfc, 0xcf, 0xbe, 0x62, 0xf8, 0xb9, + 0x0b, 0x73, 0xe9, 0xa9, 0x34, 0xb7, 0xae, 0xd1, 0x2d, 0x4e, 0xdc, 0x3b, 0x98, 0x1d, 0xd1, 0x21, + 0xd8, 0xe0, 0x83, 0x30, 0x0c, 0xb7, 0xfc, 0xba, 0x62, 0x5b, 0x60, 0x6c, 0x67, 0xb3, 0xd8, 0x56, + 0x62, 0xb2, 0xc5, 0xf1, 0x7b, 0x07, 0xb3, 0xc3, 0x1a, 0x00, 0xeb, 0x4c, 0xd0, 0x26, 0x8c, 0xd3, + 0xbf, 0x5e, 0xe4, 0x2a, 0xbe, 0x45, 0xc6, 0xf7, 0xb1, 0x3c, 0xbe, 0x1a, 0xe9, 0xe2, 0xd4, 0xbd, + 0x83, 0xd9, 0xf1, 0x04, 0x10, 0x27, 0x19, 0xda, 0x6f, 0xc1, 0xd8, 0x42, 0x14, 0x39, 0xb5, 0x1d, + 0x52, 0xe7, 0x23, 0x88, 0x5e, 0x80, 0x3e, 0xcf, 0x69, 0x12, 0x31, 0xbe, 0x17, 0x44, 0xc7, 0xf6, + 0xad, 0x3b, 0x4d, 0x72, 0x78, 0x30, 0x3b, 0x71, 0xd3, 0x73, 0xdf, 0x6c, 0x8b, 0x59, 0x41, 0x61, + 0x98, 0x51, 0xa3, 0xe7, 0x00, 0xea, 0x64, 0xcf, 0xad, 0x91, 0x8a, 0x13, 0xed, 0x88, 0xf1, 0x46, + 0xa2, 0x2c, 0x2c, 0x2b, 0x0c, 0xd6, 0xa8, 0xec, 0xbb, 0x50, 0x5a, 0xd8, 0xf3, 0xdd, 0x7a, 0xc5, + 0xaf, 0x87, 0x68, 0x17, 0xc6, 0x5b, 0x01, 0xd9, 0x22, 0x81, 0x02, 0x4d, 0x5b, 0x17, 0x8a, 0x97, + 0x86, 0x9f, 0xbb, 0x94, 0xf9, 0xb1, 0x26, 0xe9, 0x8a, 0x17, 0x05, 0xfb, 0x8b, 0x0f, 0x89, 0xfa, + 0xc6, 0x13, 0x58, 0x9c, 0xe4, 0x6c, 0xff, 0xb3, 0x02, 0x9c, 0x5e, 0x78, 0xab, 0x1d, 0x90, 0x65, + 0x37, 0xdc, 0x4d, 0xce, 0xf0, 0xba, 0x1b, 0xee, 0xae, 0xc7, 0x3d, 0xa0, 0xa6, 0xd6, 0xb2, 0x80, + 0x63, 0x45, 0x81, 0x9e, 0x85, 0x41, 0xfa, 0xfb, 0x26, 0x2e, 0x8b, 0x4f, 0x9e, 0x12, 0xc4, 0xc3, + 0xcb, 0x4e, 0xe4, 0x2c, 0x73, 0x14, 0x96, 0x34, 0x68, 0x0d, 0x86, 0x6b, 0x6c, 0x41, 0x6e, 0xaf, + 0xf9, 0x75, 0xc2, 0x06, 0xb3, 0xb4, 0xf8, 0x34, 0x25, 0x5f, 0x8a, 0xc1, 0x87, 0x07, 0xb3, 0xd3, + 0xbc, 0x6d, 0x82, 0x85, 0x86, 0xc3, 0x7a, 0x79, 0x64, 0xab, 0xf5, 0xd5, 0xc7, 0x38, 0x41, 0xc6, + 0xda, 0xba, 0xa4, 0x2d, 0x95, 0x7e, 0xb6, 0x54, 0x46, 0xb2, 0x97, 0x09, 0xba, 0x0c, 0x7d, 0xbb, + 0xae, 0x57, 0x9f, 0x1e, 0x60, 0xbc, 0xce, 0xd1, 0x31, 0xbf, 0xe6, 0x7a, 0xf5, 0xc3, 0x83, 0xd9, + 0x49, 0xa3, 0x39, 0x14, 0x88, 0x19, 0xa9, 0xfd, 0xdf, 0x2d, 0x98, 0x65, 0xb8, 0x55, 0xb7, 0x41, + 0x2a, 0x24, 0x08, 0xdd, 0x30, 0x22, 0x5e, 0x64, 0x74, 0xe8, 0x73, 0x00, 0x21, 0xa9, 0x05, 0x24, + 0xd2, 0xba, 0x54, 0x4d, 0x8c, 0xaa, 0xc2, 0x60, 0x8d, 0x8a, 0x6e, 0x08, 0xe1, 0x8e, 0x13, 0xb0, + 0xf9, 0x25, 0x3a, 0x56, 0x6d, 0x08, 0x55, 0x89, 0xc0, 0x31, 0x8d, 0xb1, 0x21, 0x14, 0xbb, 0x6d, + 0x08, 0xe8, 0x43, 0x30, 0x1e, 0x57, 0x16, 0xb6, 0x9c, 0x9a, 0xec, 0x40, 0xb6, 0x64, 0xaa, 0x26, + 0x0a, 0x27, 0x69, 0xed, 0xbf, 0x69, 0x89, 0xc9, 0x43, 0xbf, 0xfa, 0x1d, 0xfe, 0xad, 0xf6, 0x2f, + 0x58, 0x30, 0xb8, 0xe8, 0x7a, 0x75, 0xd7, 0xdb, 0x46, 0x9f, 0x82, 0x21, 0x7a, 0x36, 0xd5, 0x9d, + 0xc8, 0x11, 0xfb, 0xde, 0xfb, 0xb4, 0xb5, 0xa5, 0x8e, 0x8a, 0xb9, 0xd6, 0xee, 0x36, 0x05, 0x84, + 0x73, 0x94, 0x9a, 0xae, 0xb6, 0x1b, 0x9b, 0x9f, 0x26, 0xb5, 0x68, 0x8d, 0x44, 0x4e, 0xfc, 0x39, + 0x31, 0x0c, 0x2b, 0xae, 0xe8, 0x1a, 0x0c, 0x44, 0x4e, 0xb0, 0x4d, 0x22, 0xb1, 0x01, 0x66, 0x6e, + 0x54, 0xbc, 0x24, 0xa6, 0x2b, 0x92, 0x78, 0x35, 0x12, 0x1f, 0x0b, 0x1b, 0xac, 0x28, 0x16, 0x2c, + 0xec, 0xff, 0x3b, 0x08, 0x67, 0x97, 0xaa, 0xe5, 0x9c, 0x79, 0x75, 0x11, 0x06, 0xea, 0x81, 0xbb, + 0x47, 0x02, 0xd1, 0xcf, 0x8a, 0xcb, 0x32, 0x83, 0x62, 0x81, 0x45, 0x2f, 0xc1, 0x08, 0x3f, 0x90, + 0xae, 0x3a, 0x5e, 0xbd, 0x21, 0xbb, 0xf8, 0x94, 0xa0, 0x1e, 0xb9, 0xa5, 0xe1, 0xb0, 0x41, 0x79, + 0xc4, 0x49, 0x75, 0x31, 0xb1, 0x18, 0xf3, 0x0e, 0xbb, 0xcf, 0x5b, 0x30, 0xc1, 0xab, 0x59, 0x88, + 0xa2, 0xc0, 0xdd, 0x6c, 0x47, 0x24, 0x9c, 0xee, 0x67, 0x3b, 0xdd, 0x52, 0x56, 0x6f, 0xe5, 0xf6, + 0xc0, 0xdc, 0xad, 0x04, 0x17, 0xbe, 0x09, 0x4e, 0x8b, 0x7a, 0x27, 0x92, 0x68, 0x9c, 0xaa, 0x16, + 0x7d, 0xb7, 0x05, 0x33, 0x35, 0xdf, 0x8b, 0x02, 0xbf, 0xd1, 0x20, 0x41, 0xa5, 0xbd, 0xd9, 0x70, + 0xc3, 0x1d, 0x3e, 0x4f, 0x31, 0xd9, 0x62, 0x3b, 0x41, 0xce, 0x18, 0x2a, 0x22, 0x31, 0x86, 0xe7, + 0xef, 0x1d, 0xcc, 0xce, 0x2c, 0xe5, 0xb2, 0xc2, 0x1d, 0xaa, 0x41, 0xbb, 0x80, 0xe8, 0x51, 0x5a, + 0x8d, 0x9c, 0x6d, 0x12, 0x57, 0x3e, 0xd8, 0x7b, 0xe5, 0x67, 0xee, 0x1d, 0xcc, 0xa2, 0xf5, 0x14, + 0x0b, 0x9c, 0xc1, 0x16, 0xbd, 0x09, 0xa7, 0x28, 0x34, 0xf5, 0xad, 0x43, 0xbd, 0x57, 0x37, 0x7d, + 0xef, 0x60, 0xf6, 0xd4, 0x7a, 0x06, 0x13, 0x9c, 0xc9, 0x1a, 0x7d, 0x97, 0x05, 0x67, 0xe3, 0xcf, + 0x5f, 0xb9, 0xdb, 0x72, 0xbc, 0x7a, 0x5c, 0x71, 0xa9, 0xf7, 0x8a, 0xe9, 0x9e, 0x7c, 0x76, 0x29, + 0x8f, 0x13, 0xce, 0xaf, 0x04, 0x79, 0x30, 0x45, 0x9b, 0x96, 0xac, 0x1b, 0x7a, 0xaf, 0xfb, 0xa1, + 0x7b, 0x07, 0xb3, 0x53, 0xeb, 0x69, 0x1e, 0x38, 0x8b, 0xf1, 0xcc, 0x12, 0x9c, 0xce, 0x9c, 0x9d, + 0x68, 0x02, 0x8a, 0xbb, 0x84, 0x4b, 0x5d, 0x25, 0x4c, 0x7f, 0xa2, 0x53, 0xd0, 0xbf, 0xe7, 0x34, + 0xda, 0x62, 0x61, 0x62, 0xfe, 0xe7, 0xe5, 0xc2, 0x4b, 0x96, 0xfd, 0xcf, 0x8b, 0x30, 0xbe, 0x54, + 0x2d, 0xdf, 0xd7, 0xaa, 0xd7, 0x8f, 0xbd, 0x42, 0xc7, 0x63, 0x2f, 0x3e, 0x44, 0x8b, 0xb9, 0x87, + 0xe8, 0x9f, 0xcd, 0x58, 0xb2, 0x7d, 0x6c, 0xc9, 0x7e, 0x47, 0xce, 0x92, 0x3d, 0xe6, 0x85, 0xba, + 0x97, 0x33, 0x6b, 0xfb, 0xd9, 0x00, 0x66, 0x4a, 0x48, 0xd7, 0xfd, 0x9a, 0xd3, 0x48, 0x6e, 0xb5, + 0x47, 0x9c, 0xba, 0xc7, 0x33, 0x8e, 0x35, 0x18, 0x59, 0x72, 0x5a, 0xce, 0xa6, 0xdb, 0x70, 0x23, + 0x97, 0x84, 0xe8, 0x49, 0x28, 0x3a, 0xf5, 0x3a, 0x93, 0xee, 0x4a, 0x8b, 0xa7, 0xef, 0x1d, 0xcc, + 0x16, 0x17, 0xea, 0x54, 0xcc, 0x00, 0x45, 0xb5, 0x8f, 0x29, 0x05, 0x7a, 0x2f, 0xf4, 0xd5, 0x03, + 0xbf, 0x35, 0x5d, 0x60, 0x94, 0x74, 0x95, 0xf7, 0x2d, 0x07, 0x7e, 0x2b, 0x41, 0xca, 0x68, 0xec, + 0x5f, 0x2d, 0xc0, 0x23, 0x4b, 0xa4, 0xb5, 0xb3, 0x5a, 0xcd, 0x39, 0x2f, 0x2e, 0xc1, 0x50, 0xd3, + 0xf7, 0xdc, 0xc8, 0x0f, 0x42, 0x51, 0x35, 0x9b, 0x11, 0x6b, 0x02, 0x86, 0x15, 0x16, 0x5d, 0x80, + 0xbe, 0x56, 0x2c, 0xc4, 0x8e, 0x48, 0x01, 0x98, 0x89, 0xaf, 0x0c, 0x43, 0x29, 0xda, 0x21, 0x09, + 0xc4, 0x8c, 0x51, 0x14, 0x37, 0x43, 0x12, 0x60, 0x86, 0x89, 0x25, 0x01, 0x2a, 0x23, 0x88, 0x13, + 0x21, 0x21, 0x09, 0x50, 0x0c, 0xd6, 0xa8, 0x50, 0x05, 0x4a, 0x61, 0x62, 0x64, 0x7b, 0x5a, 0x9a, + 0xa3, 0x4c, 0x54, 0x50, 0x23, 0x19, 0x33, 0x31, 0x4e, 0xb0, 0x81, 0xae, 0xa2, 0xc2, 0xd7, 0x0a, + 0x80, 0x78, 0x17, 0x7e, 0x8b, 0x75, 0xdc, 0xcd, 0x74, 0xc7, 0xf5, 0xbe, 0x24, 0x8e, 0xab, 0xf7, + 0xfe, 0x87, 0x05, 0x8f, 0x2c, 0xb9, 0x5e, 0x9d, 0x04, 0x39, 0x13, 0xf0, 0xc1, 0xdc, 0x9d, 0x8f, + 0x26, 0xa4, 0x18, 0x53, 0xac, 0xef, 0x18, 0xa6, 0x98, 0xfd, 0x47, 0x16, 0x20, 0xfe, 0xd9, 0xef, + 0xb8, 0x8f, 0xbd, 0x99, 0xfe, 0xd8, 0x63, 0x98, 0x16, 0xf6, 0xdf, 0xb5, 0x60, 0x78, 0xa9, 0xe1, + 0xb8, 0x4d, 0xf1, 0xa9, 0x4b, 0x30, 0x29, 0x15, 0x45, 0x0c, 0xac, 0xc9, 0xfe, 0x74, 0x73, 0x9b, + 0xc4, 0x49, 0x24, 0x4e, 0xd3, 0xa3, 0x8f, 0xc3, 0x59, 0x03, 0xb8, 0x41, 0x9a, 0xad, 0x86, 0x13, + 0xe9, 0xb7, 0x02, 0x76, 0xfa, 0xe3, 0x3c, 0x22, 0x9c, 0x5f, 0xde, 0xbe, 0x0e, 0x63, 0x4b, 0x0d, + 0x97, 0x78, 0x51, 0xb9, 0xb2, 0xe4, 0x7b, 0x5b, 0xee, 0x36, 0x7a, 0x19, 0xc6, 0x22, 0xb7, 0x49, + 0xfc, 0x76, 0x54, 0x25, 0x35, 0xdf, 0x63, 0x77, 0x6d, 0xeb, 0x52, 0xff, 0x22, 0xba, 0x77, 0x30, + 0x3b, 0xb6, 0x61, 0x60, 0x70, 0x82, 0xd2, 0xfe, 0x1d, 0x3a, 0xe2, 0x7e, 0xb3, 0xe5, 0x7b, 0xc4, + 0x8b, 0x96, 0x7c, 0xaf, 0xce, 0x75, 0x32, 0x2f, 0x43, 0x5f, 0x44, 0x47, 0x90, 0x7f, 0xf9, 0x45, + 0xb9, 0xb4, 0xe9, 0xb8, 0x1d, 0x1e, 0xcc, 0x9e, 0x49, 0x97, 0x60, 0x23, 0xcb, 0xca, 0xa0, 0xef, + 0x80, 0x81, 0x30, 0x72, 0xa2, 0x76, 0x28, 0x3e, 0xf5, 0x51, 0x39, 0xfe, 0x55, 0x06, 0x3d, 0x3c, + 0x98, 0x1d, 0x57, 0xc5, 0x38, 0x08, 0x8b, 0x02, 0xe8, 0x29, 0x18, 0x6c, 0x92, 0x30, 0x74, 0xb6, + 0xe5, 0xf9, 0x3d, 0x2e, 0xca, 0x0e, 0xae, 0x71, 0x30, 0x96, 0x78, 0xf4, 0x18, 0xf4, 0x93, 0x20, + 0xf0, 0x03, 0xb1, 0xab, 0x8c, 0x0a, 0xc2, 0xfe, 0x15, 0x0a, 0xc4, 0x1c, 0x67, 0xff, 0x5b, 0x0b, + 0xc6, 0x55, 0x5b, 0x79, 0x5d, 0x27, 0x70, 0x6f, 0xfa, 0x18, 0x40, 0x4d, 0x7e, 0x60, 0xc8, 0xce, + 0xbb, 0xe1, 0xe7, 0x2e, 0x66, 0x8a, 0x16, 0xa9, 0x6e, 0x8c, 0x39, 0x2b, 0x50, 0x88, 0x35, 0x6e, + 0xf6, 0x3f, 0xb2, 0x60, 0x2a, 0xf1, 0x45, 0xd7, 0xdd, 0x30, 0x42, 0x6f, 0xa4, 0xbe, 0x6a, 0xae, + 0xb7, 0xaf, 0xa2, 0xa5, 0xd9, 0x37, 0xa9, 0xc5, 0x27, 0x21, 0xda, 0x17, 0x5d, 0x85, 0x7e, 0x37, + 0x22, 0x4d, 0xf9, 0x31, 0x8f, 0x75, 0xfc, 0x18, 0xde, 0xaa, 0x78, 0x44, 0xca, 0xb4, 0x24, 0xe6, + 0x0c, 0xec, 0x5f, 0x2d, 0x42, 0x89, 0x4f, 0xdb, 0x35, 0xa7, 0x75, 0x02, 0x63, 0xf1, 0x34, 0x94, + 0xdc, 0x66, 0xb3, 0x1d, 0x39, 0x9b, 0xe2, 0x00, 0x1a, 0xe2, 0x9b, 0x41, 0x59, 0x02, 0x71, 0x8c, + 0x47, 0x65, 0xe8, 0x63, 0x4d, 0xe1, 0x5f, 0xf9, 0x64, 0xf6, 0x57, 0x8a, 0xb6, 0xcf, 0x2d, 0x3b, + 0x91, 0xc3, 0x65, 0x3f, 0x75, 0xf2, 0x51, 0x10, 0x66, 0x2c, 0x90, 0x03, 0xb0, 0xe9, 0x7a, 0x4e, + 0xb0, 0x4f, 0x61, 0xd3, 0x45, 0xc6, 0xf0, 0xd9, 0xce, 0x0c, 0x17, 0x15, 0x3d, 0x67, 0xab, 0x3e, + 0x2c, 0x46, 0x60, 0x8d, 0xe9, 0xcc, 0x07, 0xa0, 0xa4, 0x88, 0x8f, 0x22, 0xc2, 0xcd, 0x7c, 0x08, + 0xc6, 0x13, 0x75, 0x75, 0x2b, 0x3e, 0xa2, 0x4b, 0x80, 0xbf, 0xc8, 0xb6, 0x0c, 0xd1, 0xea, 0x15, + 0x6f, 0x4f, 0xec, 0x9c, 0x6f, 0xc1, 0xa9, 0x46, 0xc6, 0xde, 0x2b, 0xc6, 0xb5, 0xf7, 0xbd, 0xfa, + 0x11, 0xf1, 0xd9, 0xa7, 0xb2, 0xb0, 0x38, 0xb3, 0x0e, 0x2a, 0xd5, 0xf8, 0x2d, 0xba, 0x40, 0x9c, + 0x86, 0x7e, 0x41, 0xb8, 0x21, 0x60, 0x58, 0x61, 0xe9, 0x7e, 0x77, 0x4a, 0x35, 0xfe, 0x1a, 0xd9, + 0xaf, 0x92, 0x06, 0xa9, 0x45, 0x7e, 0xf0, 0x4d, 0x6d, 0xfe, 0x39, 0xde, 0xfb, 0x7c, 0xbb, 0x1c, + 0x16, 0x0c, 0x8a, 0xd7, 0xc8, 0x3e, 0x1f, 0x0a, 0xfd, 0xeb, 0x8a, 0x1d, 0xbf, 0xee, 0x2b, 0x16, + 0x8c, 0xaa, 0xaf, 0x3b, 0x81, 0x7d, 0x61, 0xd1, 0xdc, 0x17, 0xce, 0x75, 0x9c, 0xe0, 0x39, 0x3b, + 0xc2, 0xd7, 0x0a, 0x70, 0x56, 0xd1, 0xd0, 0xdb, 0x0c, 0xff, 0x23, 0x66, 0xd5, 0x3c, 0x94, 0x3c, + 0xa5, 0xd7, 0xb3, 0x4c, 0x85, 0x5a, 0xac, 0xd5, 0x8b, 0x69, 0xa8, 0x50, 0xea, 0xc5, 0xc7, 0xec, + 0x88, 0xae, 0xf0, 0x16, 0xca, 0xed, 0x45, 0x28, 0xb6, 0xdd, 0xba, 0x38, 0x60, 0xde, 0x27, 0x7b, + 0xfb, 0x66, 0x79, 0xf9, 0xf0, 0x60, 0xf6, 0xd1, 0x3c, 0x63, 0x0b, 0x3d, 0xd9, 0xc2, 0xb9, 0x9b, + 0xe5, 0x65, 0x4c, 0x0b, 0xa3, 0x05, 0x18, 0x97, 0x27, 0xf4, 0x2d, 0x2a, 0x20, 0xfa, 0x9e, 0x38, + 0x87, 0x94, 0xd6, 0x1a, 0x9b, 0x68, 0x9c, 0xa4, 0x47, 0xcb, 0x30, 0xb1, 0xdb, 0xde, 0x24, 0x0d, + 0x12, 0xf1, 0x0f, 0xbe, 0x46, 0xb8, 0x4e, 0xb7, 0x14, 0xdf, 0x25, 0xaf, 0x25, 0xf0, 0x38, 0x55, + 0xc2, 0xfe, 0x53, 0x76, 0x1e, 0x88, 0xde, 0xab, 0x04, 0x3e, 0x9d, 0x58, 0x94, 0xfb, 0x37, 0x73, + 0x3a, 0xf7, 0x32, 0x2b, 0xae, 0x91, 0xfd, 0x0d, 0x9f, 0xde, 0x25, 0xb2, 0x67, 0x85, 0x31, 0xe7, + 0xfb, 0x3a, 0xce, 0xf9, 0x9f, 0x2d, 0xc0, 0x69, 0xd5, 0x03, 0x86, 0xd8, 0xfa, 0xad, 0xde, 0x07, + 0x97, 0x61, 0xb8, 0x4e, 0xb6, 0x9c, 0x76, 0x23, 0x52, 0x06, 0x86, 0x7e, 0x6e, 0x64, 0x5a, 0x8e, + 0xc1, 0x58, 0xa7, 0x39, 0x42, 0xb7, 0xfd, 0xcf, 0x61, 0x76, 0x10, 0x47, 0x0e, 0x9d, 0xe3, 0x6a, + 0xd5, 0x58, 0xb9, 0xab, 0xe6, 0x31, 0xe8, 0x77, 0x9b, 0x54, 0x30, 0x2b, 0x98, 0xf2, 0x56, 0x99, + 0x02, 0x31, 0xc7, 0xa1, 0x27, 0x60, 0xb0, 0xe6, 0x37, 0x9b, 0x8e, 0x57, 0x67, 0x47, 0x5e, 0x69, + 0x71, 0x98, 0xca, 0x6e, 0x4b, 0x1c, 0x84, 0x25, 0x0e, 0x3d, 0x02, 0x7d, 0x4e, 0xb0, 0xcd, 0xb5, + 0x2e, 0xa5, 0xc5, 0x21, 0x5a, 0xd3, 0x42, 0xb0, 0x1d, 0x62, 0x06, 0xa5, 0x97, 0xc6, 0x3b, 0x7e, + 0xb0, 0xeb, 0x7a, 0xdb, 0xcb, 0x6e, 0x20, 0x96, 0x84, 0x3a, 0x0b, 0x6f, 0x2b, 0x0c, 0xd6, 0xa8, + 0xd0, 0x2a, 0xf4, 0xb7, 0xfc, 0x20, 0x0a, 0xa7, 0x07, 0x58, 0x77, 0x3f, 0x9a, 0xb3, 0x11, 0xf1, + 0xaf, 0xad, 0xf8, 0x41, 0x14, 0x7f, 0x00, 0xfd, 0x17, 0x62, 0x5e, 0x1c, 0x5d, 0x87, 0x41, 0xe2, + 0xed, 0xad, 0x06, 0x7e, 0x73, 0x7a, 0x2a, 0x9f, 0xd3, 0x0a, 0x27, 0xe1, 0xd3, 0x2c, 0x96, 0x51, + 0x05, 0x18, 0x4b, 0x16, 0xe8, 0x3b, 0xa0, 0x48, 0xbc, 0xbd, 0xe9, 0x41, 0xc6, 0x69, 0x26, 0x87, + 0xd3, 0x2d, 0x27, 0x88, 0xf7, 0xfc, 0x15, 0x6f, 0x0f, 0xd3, 0x32, 0xe8, 0xa3, 0x50, 0x92, 0x1b, + 0x46, 0x28, 0xd4, 0x99, 0x99, 0x13, 0x56, 0x6e, 0x33, 0x98, 0xbc, 0xd9, 0x76, 0x03, 0xd2, 0x24, + 0x5e, 0x14, 0xc6, 0x3b, 0xa4, 0xc4, 0x86, 0x38, 0xe6, 0x86, 0x3e, 0x2a, 0x75, 0xe8, 0x6b, 0x7e, + 0xdb, 0x8b, 0xc2, 0xe9, 0x12, 0x6b, 0x5e, 0xa6, 0x75, 0xf3, 0x56, 0x4c, 0x97, 0x54, 0xb2, 0xf3, + 0xc2, 0xd8, 0x60, 0x85, 0x3e, 0x01, 0xa3, 0xfc, 0x3f, 0xb7, 0x11, 0x86, 0xd3, 0xa7, 0x19, 0xef, + 0x0b, 0xf9, 0xbc, 0x39, 0xe1, 0xe2, 0x69, 0xc1, 0x7c, 0x54, 0x87, 0x86, 0xd8, 0xe4, 0x86, 0x30, + 0x8c, 0x36, 0xdc, 0x3d, 0xe2, 0x91, 0x30, 0xac, 0x04, 0xfe, 0x26, 0x11, 0x2a, 0xcf, 0xb3, 0xd9, + 0x36, 0x45, 0x7f, 0x93, 0x2c, 0x4e, 0x52, 0x9e, 0xd7, 0xf5, 0x32, 0xd8, 0x64, 0x81, 0x6e, 0xc2, + 0x18, 0xbd, 0x63, 0xba, 0x31, 0xd3, 0xe1, 0x6e, 0x4c, 0xd9, 0xbd, 0x0a, 0x1b, 0x85, 0x70, 0x82, + 0x09, 0xba, 0x01, 0x23, 0x61, 0xe4, 0x04, 0x51, 0xbb, 0xc5, 0x99, 0x9e, 0xe9, 0xc6, 0x94, 0x99, + 0xa4, 0xab, 0x5a, 0x11, 0x6c, 0x30, 0x40, 0xaf, 0x41, 0xa9, 0xe1, 0x6e, 0x91, 0xda, 0x7e, 0xad, + 0x41, 0xa6, 0x47, 0x18, 0xb7, 0xcc, 0x4d, 0xe5, 0xba, 0x24, 0xe2, 0x72, 0xae, 0xfa, 0x8b, 0xe3, + 0xe2, 0xe8, 0x16, 0x9c, 0x89, 0x48, 0xd0, 0x74, 0x3d, 0x87, 0x6e, 0x06, 0xe2, 0x6a, 0xc5, 0x4c, + 0xbd, 0xa3, 0x6c, 0xb5, 0x9d, 0x17, 0xa3, 0x71, 0x66, 0x23, 0x93, 0x0a, 0xe7, 0x94, 0x46, 0x77, + 0x61, 0x3a, 0x03, 0xe3, 0x37, 0xdc, 0xda, 0xfe, 0xf4, 0x29, 0xc6, 0xf9, 0x83, 0x82, 0xf3, 0xf4, + 0x46, 0x0e, 0xdd, 0x61, 0x07, 0x1c, 0xce, 0xe5, 0x8e, 0x6e, 0xc0, 0x38, 0xdb, 0x81, 0x2a, 0xed, + 0x46, 0x43, 0x54, 0x38, 0xc6, 0x2a, 0x7c, 0x42, 0x9e, 0xc7, 0x65, 0x13, 0x7d, 0x78, 0x30, 0x0b, + 0xf1, 0x3f, 0x9c, 0x2c, 0x8d, 0x36, 0x99, 0x55, 0xb1, 0x1d, 0xb8, 0xd1, 0x3e, 0xdd, 0x37, 0xc8, + 0xdd, 0x68, 0x7a, 0xbc, 0xa3, 0x86, 0x45, 0x27, 0x55, 0xa6, 0x47, 0x1d, 0x88, 0x93, 0x0c, 0xe9, + 0x96, 0x1a, 0x46, 0x75, 0xd7, 0x9b, 0x9e, 0xe0, 0xf7, 0x12, 0xb9, 0x23, 0x55, 0x29, 0x10, 0x73, + 0x1c, 0xb3, 0x28, 0xd2, 0x1f, 0x37, 0xe8, 0xc9, 0x35, 0xc9, 0x08, 0x63, 0x8b, 0xa2, 0x44, 0xe0, + 0x98, 0x86, 0x0a, 0x93, 0x51, 0xb4, 0x3f, 0x8d, 0x18, 0xa9, 0xda, 0x58, 0x36, 0x36, 0x3e, 0x8a, + 0x29, 0xdc, 0xde, 0x84, 0x31, 0xb5, 0x11, 0xb2, 0x3e, 0x41, 0xb3, 0xd0, 0xcf, 0xc4, 0x27, 0xa1, + 0x0f, 0x2c, 0xd1, 0x26, 0x30, 0xd1, 0x0a, 0x73, 0x38, 0x6b, 0x82, 0xfb, 0x16, 0x59, 0xdc, 0x8f, + 0x08, 0xbf, 0xd3, 0x17, 0xb5, 0x26, 0x48, 0x04, 0x8e, 0x69, 0xec, 0xff, 0xc7, 0xc5, 0xd0, 0x78, + 0xb7, 0xed, 0xe1, 0x7c, 0x79, 0x06, 0x86, 0x76, 0xfc, 0x30, 0xa2, 0xd4, 0xac, 0x8e, 0xfe, 0x58, + 0xf0, 0xbc, 0x2a, 0xe0, 0x58, 0x51, 0xa0, 0x57, 0x60, 0xb4, 0xa6, 0x57, 0x20, 0x0e, 0x47, 0xb5, + 0x8d, 0x18, 0xb5, 0x63, 0x93, 0x16, 0xbd, 0x04, 0x43, 0xcc, 0x4b, 0xa6, 0xe6, 0x37, 0x84, 0xd4, + 0x26, 0x4f, 0xf8, 0xa1, 0x8a, 0x80, 0x1f, 0x6a, 0xbf, 0xb1, 0xa2, 0x46, 0x17, 0x61, 0x80, 0x36, + 0xa1, 0x5c, 0x11, 0xc7, 0x92, 0x52, 0x6d, 0x5d, 0x65, 0x50, 0x2c, 0xb0, 0xf6, 0x5f, 0x2c, 0x68, + 0xbd, 0x4c, 0xef, 0xc3, 0x04, 0x55, 0x60, 0xf0, 0x8e, 0xe3, 0x46, 0xae, 0xb7, 0x2d, 0xe4, 0x8f, + 0xa7, 0x3a, 0x9e, 0x51, 0xac, 0xd0, 0x6d, 0x5e, 0x80, 0x9f, 0xa2, 0xe2, 0x0f, 0x96, 0x6c, 0x28, + 0xc7, 0xa0, 0xed, 0x79, 0x94, 0x63, 0xa1, 0x57, 0x8e, 0x98, 0x17, 0xe0, 0x1c, 0xc5, 0x1f, 0x2c, + 0xd9, 0xa0, 0x37, 0x00, 0xe4, 0x0a, 0x23, 0x75, 0xe1, 0x9d, 0xf2, 0x4c, 0x77, 0xa6, 0x1b, 0xaa, + 0xcc, 0xe2, 0x18, 0x3d, 0xa3, 0xe3, 0xff, 0x58, 0xe3, 0x67, 0x47, 0x4c, 0x4e, 0x4b, 0x37, 0x06, + 0x7d, 0x9c, 0x4e, 0x71, 0x27, 0x88, 0x48, 0x7d, 0x21, 0x12, 0x9d, 0xf3, 0xde, 0xde, 0x2e, 0x29, + 0x1b, 0x6e, 0x93, 0xe8, 0xcb, 0x41, 0x30, 0xc1, 0x31, 0x3f, 0xfb, 0xe7, 0x8b, 0x30, 0x9d, 0xd7, + 0x5c, 0x3a, 0xe9, 0xc8, 0x5d, 0x37, 0x5a, 0xa2, 0xe2, 0x95, 0x65, 0x4e, 0xba, 0x15, 0x01, 0xc7, + 0x8a, 0x82, 0x8e, 0x7e, 0xe8, 0x6e, 0xcb, 0x3b, 0x66, 0x7f, 0x3c, 0xfa, 0x55, 0x06, 0xc5, 0x02, + 0x4b, 0xe9, 0x02, 0xe2, 0x84, 0xc2, 0xfd, 0x49, 0x9b, 0x25, 0x98, 0x41, 0xb1, 0xc0, 0xea, 0xda, + 0xae, 0xbe, 0x2e, 0xda, 0x2e, 0xa3, 0x8b, 0xfa, 0x8f, 0xb7, 0x8b, 0xd0, 0x27, 0x01, 0xb6, 0x5c, + 0xcf, 0x0d, 0x77, 0x18, 0xf7, 0x81, 0x23, 0x73, 0x57, 0xc2, 0xd9, 0xaa, 0xe2, 0x82, 0x35, 0x8e, + 0xe8, 0x45, 0x18, 0x56, 0x0b, 0xb0, 0xbc, 0xcc, 0x6c, 0xc1, 0x9a, 0x6f, 0x4d, 0xbc, 0x1b, 0x2d, + 0x63, 0x9d, 0xce, 0xfe, 0x74, 0x72, 0xbe, 0x88, 0x15, 0xa0, 0xf5, 0xaf, 0xd5, 0x6b, 0xff, 0x16, + 0x3a, 0xf7, 0xaf, 0xfd, 0x8d, 0x22, 0x8c, 0x1b, 0x95, 0xb5, 0xc3, 0x1e, 0xf6, 0xac, 0x2b, 0x74, + 0x03, 0x77, 0x22, 0x22, 0xd6, 0x9f, 0xdd, 0x7d, 0xa9, 0xe8, 0x9b, 0x3c, 0x5d, 0x01, 0xbc, 0x3c, + 0xfa, 0x24, 0x94, 0x1a, 0x4e, 0xc8, 0x34, 0x67, 0x44, 0xac, 0xbb, 0x5e, 0x98, 0xc5, 0x17, 0x13, + 0x27, 0x8c, 0xb4, 0x53, 0x93, 0xf3, 0x8e, 0x59, 0xd2, 0x93, 0x86, 0xca, 0x27, 0xd2, 0xbf, 0x4e, + 0x35, 0x82, 0x0a, 0x31, 0xfb, 0x98, 0xe3, 0xd0, 0x4b, 0x30, 0x12, 0x10, 0x36, 0x2b, 0x96, 0xa8, + 0x34, 0xc7, 0xa6, 0x59, 0x7f, 0x2c, 0xf6, 0x61, 0x0d, 0x87, 0x0d, 0xca, 0xf8, 0x6e, 0x30, 0xd0, + 0xe1, 0x6e, 0xf0, 0x14, 0x0c, 0xb2, 0x1f, 0x6a, 0x06, 0xa8, 0xd1, 0x28, 0x73, 0x30, 0x96, 0xf8, + 0xe4, 0x84, 0x19, 0xea, 0x6d, 0xc2, 0xd0, 0xdb, 0x87, 0x98, 0xd4, 0xcc, 0x0e, 0x3f, 0xc4, 0x77, + 0x39, 0x31, 0xe5, 0xb1, 0xc4, 0xd9, 0xef, 0x85, 0xb1, 0x65, 0x87, 0x34, 0x7d, 0x6f, 0xc5, 0xab, + 0xb7, 0x7c, 0xd7, 0x8b, 0xd0, 0x34, 0xf4, 0xb1, 0x43, 0x84, 0x6f, 0x01, 0x7d, 0xb4, 0x22, 0xcc, + 0x20, 0xf6, 0x36, 0x9c, 0x5e, 0xf6, 0xef, 0x78, 0x77, 0x9c, 0xa0, 0xbe, 0x50, 0x29, 0x6b, 0xf7, + 0xeb, 0x75, 0x79, 0xbf, 0xe3, 0x6e, 0x6d, 0x99, 0x5b, 0xaf, 0x56, 0x92, 0x8b, 0xb5, 0xab, 0x6e, + 0x83, 0xe4, 0x68, 0x41, 0xfe, 0x4a, 0xc1, 0xa8, 0x29, 0xa6, 0x57, 0x76, 0x38, 0x2b, 0xd7, 0x0e, + 0xf7, 0x3a, 0x0c, 0x6d, 0xb9, 0xa4, 0x51, 0xc7, 0x64, 0x4b, 0xcc, 0xc4, 0x27, 0xf3, 0x3d, 0x75, + 0x56, 0x29, 0xa5, 0xd4, 0x7a, 0xf1, 0xdb, 0xe1, 0xaa, 0x28, 0x8c, 0x15, 0x1b, 0xb4, 0x0b, 0x13, + 0xf2, 0xc2, 0x20, 0xb1, 0x62, 0x5e, 0x3e, 0xd5, 0xe9, 0x16, 0x62, 0x32, 0x3f, 0x75, 0xef, 0x60, + 0x76, 0x02, 0x27, 0xd8, 0xe0, 0x14, 0x63, 0x7a, 0x1d, 0x6c, 0xd2, 0x1d, 0xb8, 0x8f, 0x75, 0x3f, + 0xbb, 0x0e, 0xb2, 0x9b, 0x2d, 0x83, 0xda, 0x3f, 0x66, 0xc1, 0x43, 0xa9, 0x9e, 0x11, 0x37, 0xfc, + 0x63, 0x1e, 0x85, 0xe4, 0x8d, 0xbb, 0xd0, 0xfd, 0xc6, 0x6d, 0xff, 0x2d, 0x0b, 0x4e, 0xad, 0x34, + 0x5b, 0xd1, 0xfe, 0xb2, 0x6b, 0x1a, 0xcd, 0x3e, 0x00, 0x03, 0x4d, 0x52, 0x77, 0xdb, 0x4d, 0x31, + 0x72, 0xb3, 0x72, 0x97, 0x5a, 0x63, 0xd0, 0xc3, 0x83, 0xd9, 0xd1, 0x6a, 0xe4, 0x07, 0xce, 0x36, + 0xe1, 0x00, 0x2c, 0xc8, 0xd9, 0x5e, 0xef, 0xbe, 0x45, 0xae, 0xbb, 0x4d, 0x57, 0x7a, 0x5e, 0x75, + 0xd4, 0xd9, 0xcd, 0xc9, 0x0e, 0x9d, 0x7b, 0xbd, 0xed, 0x78, 0x91, 0x1b, 0xed, 0x0b, 0x7b, 0x97, + 0x64, 0x82, 0x63, 0x7e, 0xf6, 0xd7, 0x2d, 0x18, 0x97, 0xf3, 0x7e, 0xa1, 0x5e, 0x0f, 0x48, 0x18, + 0xa2, 0x19, 0x28, 0xb8, 0x2d, 0xd1, 0x4a, 0x10, 0xad, 0x2c, 0x94, 0x2b, 0xb8, 0xe0, 0xb6, 0xa4, + 0x58, 0xc6, 0x36, 0xc2, 0xa2, 0x69, 0xfa, 0xbb, 0x2a, 0xe0, 0x58, 0x51, 0xa0, 0x4b, 0x30, 0xe4, + 0xf9, 0x75, 0x6e, 0xe7, 0xe2, 0x47, 0x1a, 0x9b, 0x60, 0xeb, 0x02, 0x86, 0x15, 0x16, 0x55, 0xa0, + 0xc4, 0x1d, 0xc3, 0xe2, 0x49, 0xdb, 0x93, 0x7b, 0x19, 0xfb, 0xb2, 0x0d, 0x59, 0x12, 0xc7, 0x4c, + 0xec, 0x5f, 0xb1, 0x60, 0x44, 0x7e, 0x59, 0x8f, 0x32, 0x27, 0x5d, 0x5a, 0xb1, 0xbc, 0x19, 0x2f, + 0x2d, 0x2a, 0x33, 0x32, 0x8c, 0x21, 0x2a, 0x16, 0x8f, 0x24, 0x2a, 0x5e, 0x86, 0x61, 0xa7, 0xd5, + 0xaa, 0x98, 0x72, 0x26, 0x9b, 0x4a, 0x0b, 0x31, 0x18, 0xeb, 0x34, 0xf6, 0x8f, 0x16, 0x60, 0x4c, + 0x7e, 0x41, 0xb5, 0xbd, 0x19, 0x92, 0x08, 0x6d, 0x40, 0xc9, 0xe1, 0xa3, 0x44, 0xe4, 0x24, 0x7f, + 0x2c, 0x5b, 0x8f, 0x60, 0x0c, 0x69, 0x7c, 0xe0, 0x2f, 0xc8, 0xd2, 0x38, 0x66, 0x84, 0x1a, 0x30, + 0xe9, 0xf9, 0x11, 0xdb, 0xfc, 0x15, 0xbe, 0x93, 0x69, 0x27, 0xc9, 0xfd, 0xac, 0xe0, 0x3e, 0xb9, + 0x9e, 0xe4, 0x82, 0xd3, 0x8c, 0xd1, 0x8a, 0xd4, 0xcd, 0x14, 0xf3, 0x95, 0x01, 0xfa, 0xc0, 0x65, + 0xab, 0x66, 0xec, 0x5f, 0xb2, 0xa0, 0x24, 0xc9, 0x4e, 0xc2, 0x8a, 0xb7, 0x06, 0x83, 0x21, 0x1b, + 0x04, 0xd9, 0x35, 0x76, 0xa7, 0x86, 0xf3, 0xf1, 0x8a, 0xcf, 0x34, 0xfe, 0x3f, 0xc4, 0x92, 0x07, + 0x53, 0xcd, 0xab, 0xe6, 0xbf, 0x43, 0x54, 0xf3, 0xaa, 0x3d, 0x39, 0x87, 0xd2, 0x1f, 0xb0, 0x36, + 0x6b, 0xba, 0x2e, 0x2a, 0x7a, 0xb5, 0x02, 0xb2, 0xe5, 0xde, 0x4d, 0x8a, 0x5e, 0x15, 0x06, 0xc5, + 0x02, 0x8b, 0xde, 0x80, 0x91, 0x9a, 0xd4, 0xc9, 0xc6, 0x2b, 0xfc, 0x62, 0x47, 0xfb, 0x80, 0x32, + 0x25, 0x71, 0x5d, 0xc8, 0x92, 0x56, 0x1e, 0x1b, 0xdc, 0x4c, 0xc7, 0x87, 0x62, 0x37, 0xc7, 0x87, + 0x98, 0x6f, 0xbe, 0x1b, 0xc0, 0x8f, 0x5b, 0x30, 0xc0, 0x75, 0x71, 0xbd, 0xa9, 0x42, 0x35, 0xcb, + 0x5a, 0xdc, 0x77, 0xb7, 0x28, 0x50, 0x58, 0xca, 0xd0, 0x1a, 0x94, 0xd8, 0x0f, 0xa6, 0x4b, 0x2c, + 0xe6, 0xbf, 0x4b, 0xe0, 0xb5, 0xea, 0x0d, 0xbc, 0x25, 0x8b, 0xe1, 0x98, 0x83, 0xfd, 0x23, 0x45, + 0xba, 0xbb, 0xc5, 0xa4, 0xc6, 0xa1, 0x6f, 0x3d, 0xb8, 0x43, 0xbf, 0xf0, 0xa0, 0x0e, 0xfd, 0x6d, + 0x18, 0xaf, 0x69, 0x76, 0xb8, 0x78, 0x24, 0x2f, 0x75, 0x9c, 0x24, 0x9a, 0xc9, 0x8e, 0x6b, 0x59, + 0x96, 0x4c, 0x26, 0x38, 0xc9, 0x15, 0x7d, 0x1c, 0x46, 0xf8, 0x38, 0x8b, 0x5a, 0xb8, 0xef, 0xc8, + 0x13, 0xf9, 0xf3, 0x45, 0xaf, 0x82, 0x6b, 0xe5, 0xb4, 0xe2, 0xd8, 0x60, 0x66, 0xff, 0xb1, 0x05, + 0x68, 0xa5, 0xb5, 0x43, 0x9a, 0x24, 0x70, 0x1a, 0xb1, 0x3a, 0xfd, 0x07, 0x2d, 0x98, 0x26, 0x29, + 0xf0, 0x92, 0xdf, 0x6c, 0x8a, 0x4b, 0x4b, 0xce, 0xbd, 0x7a, 0x25, 0xa7, 0x8c, 0x7a, 0xb8, 0x31, + 0x9d, 0x47, 0x81, 0x73, 0xeb, 0x43, 0x6b, 0x30, 0xc5, 0x4f, 0x49, 0x85, 0xd0, 0xfc, 0x50, 0x1e, + 0x16, 0x8c, 0xa7, 0x36, 0xd2, 0x24, 0x38, 0xab, 0x9c, 0xfd, 0x3d, 0x23, 0x90, 0xdb, 0x8a, 0x77, + 0xed, 0x08, 0xef, 0xda, 0x11, 0xde, 0xb5, 0x23, 0xbc, 0x6b, 0x47, 0x78, 0xd7, 0x8e, 0xf0, 0x6d, + 0x6f, 0x47, 0xf8, 0x4b, 0x16, 0x9c, 0x56, 0xc7, 0x80, 0x71, 0xf1, 0xfd, 0x0c, 0x4c, 0xf1, 0xe5, + 0x66, 0xf8, 0x2e, 0x8a, 0x63, 0xef, 0x72, 0xe6, 0xcc, 0x4d, 0xf8, 0xd8, 0x1a, 0x05, 0xf9, 0x63, + 0x85, 0x0c, 0x04, 0xce, 0xaa, 0xc6, 0xfe, 0xf9, 0x21, 0xe8, 0x5f, 0xd9, 0x23, 0x5e, 0x74, 0x02, + 0x57, 0x84, 0x1a, 0x8c, 0xb9, 0xde, 0x9e, 0xdf, 0xd8, 0x23, 0x75, 0x8e, 0x3f, 0xca, 0x4d, 0xf6, + 0x8c, 0x60, 0x3d, 0x56, 0x36, 0x58, 0xe0, 0x04, 0xcb, 0x07, 0xa1, 0x4d, 0xbe, 0x02, 0x03, 0x7c, + 0x13, 0x17, 0xaa, 0xe4, 0xcc, 0x3d, 0x9b, 0x75, 0xa2, 0x38, 0x9a, 0x62, 0x4d, 0x37, 0x3f, 0x24, + 0x44, 0x71, 0xf4, 0x69, 0x18, 0xdb, 0x72, 0x83, 0x30, 0xda, 0x70, 0x9b, 0x24, 0x8c, 0x9c, 0x66, + 0xeb, 0x3e, 0xb4, 0xc7, 0xaa, 0x1f, 0x56, 0x0d, 0x4e, 0x38, 0xc1, 0x19, 0x6d, 0xc3, 0x68, 0xc3, + 0xd1, 0xab, 0x1a, 0x3c, 0x72, 0x55, 0xea, 0x74, 0xb8, 0xae, 0x33, 0xc2, 0x26, 0x5f, 0xba, 0x9c, + 0x6a, 0x4c, 0x01, 0x3a, 0xc4, 0xd4, 0x02, 0x6a, 0x39, 0x71, 0xcd, 0x27, 0xc7, 0x51, 0x41, 0x87, + 0x39, 0xc8, 0x96, 0x4c, 0x41, 0x47, 0x73, 0x83, 0xfd, 0x14, 0x94, 0x08, 0xed, 0x42, 0xca, 0x58, + 0x1c, 0x30, 0xf3, 0xbd, 0xb5, 0x75, 0xcd, 0xad, 0x05, 0xbe, 0xa9, 0xb7, 0x5f, 0x91, 0x9c, 0x70, + 0xcc, 0x14, 0x2d, 0xc1, 0x40, 0x48, 0x02, 0x97, 0x84, 0xe2, 0xa8, 0xe9, 0x30, 0x8c, 0x8c, 0x8c, + 0xbf, 0x86, 0xe1, 0xbf, 0xb1, 0x28, 0x4a, 0xa7, 0x97, 0xc3, 0x54, 0x9a, 0xec, 0x30, 0xd0, 0xa6, + 0xd7, 0x02, 0x83, 0x62, 0x81, 0x45, 0xaf, 0xc1, 0x60, 0x40, 0x1a, 0xcc, 0x30, 0x34, 0xda, 0xfb, + 0x24, 0xe7, 0x76, 0x26, 0x5e, 0x0e, 0x4b, 0x06, 0xe8, 0x1a, 0xa0, 0x80, 0x50, 0x41, 0xc9, 0xf5, + 0xb6, 0x95, 0xdb, 0xa8, 0xd8, 0x68, 0x95, 0x40, 0x8a, 0x63, 0x0a, 0xf9, 0x10, 0x0a, 0x67, 0x14, + 0x43, 0x57, 0x60, 0x52, 0x41, 0xcb, 0x5e, 0x18, 0x39, 0x74, 0x83, 0x1b, 0x67, 0xbc, 0x94, 0x9e, + 0x02, 0x27, 0x09, 0x70, 0xba, 0x8c, 0xfd, 0x25, 0x0b, 0x78, 0x3f, 0x9f, 0xc0, 0xed, 0xfc, 0x55, + 0xf3, 0x76, 0x7e, 0x36, 0x77, 0xe4, 0x72, 0x6e, 0xe6, 0x5f, 0xb2, 0x60, 0x58, 0x1b, 0xd9, 0x78, + 0xce, 0x5a, 0x1d, 0xe6, 0x6c, 0x1b, 0x26, 0xe8, 0x4c, 0xbf, 0xb1, 0x19, 0x92, 0x60, 0x8f, 0xd4, + 0xd9, 0xc4, 0x2c, 0xdc, 0xdf, 0xc4, 0x54, 0x2e, 0x6a, 0xd7, 0x13, 0x0c, 0x71, 0xaa, 0x0a, 0xfb, + 0x53, 0xb2, 0xa9, 0xca, 0xa3, 0xaf, 0xa6, 0xc6, 0x3c, 0xe1, 0xd1, 0xa7, 0x46, 0x15, 0xc7, 0x34, + 0x74, 0xa9, 0xed, 0xf8, 0x61, 0x94, 0xf4, 0xe8, 0xbb, 0xea, 0x87, 0x11, 0x66, 0x18, 0xfb, 0x79, + 0x80, 0x95, 0xbb, 0xa4, 0xc6, 0x67, 0xac, 0x7e, 0x79, 0xb0, 0xf2, 0x2f, 0x0f, 0xf6, 0x6f, 0x5a, + 0x30, 0xb6, 0xba, 0x64, 0x9c, 0x5c, 0x73, 0x00, 0xfc, 0xc6, 0x73, 0xfb, 0xf6, 0xba, 0x34, 0x87, + 0x73, 0x8b, 0xa6, 0x82, 0x62, 0x8d, 0x02, 0x9d, 0x85, 0x62, 0xa3, 0xed, 0x09, 0xf5, 0xe1, 0x20, + 0x3d, 0x1e, 0xaf, 0xb7, 0x3d, 0x4c, 0x61, 0xda, 0x23, 0x88, 0x62, 0xcf, 0x8f, 0x20, 0xba, 0x06, + 0x3f, 0x40, 0xb3, 0xd0, 0x7f, 0xe7, 0x8e, 0x5b, 0xe7, 0x4f, 0x4c, 0x85, 0xa9, 0xfe, 0xf6, 0xed, + 0xf2, 0x72, 0x88, 0x39, 0xdc, 0xfe, 0x42, 0x11, 0x66, 0x56, 0x1b, 0xe4, 0xee, 0xdb, 0x7c, 0x66, + 0xdb, 0xeb, 0x13, 0x8e, 0xa3, 0x29, 0x62, 0x8e, 0xfa, 0x4c, 0xa7, 0x7b, 0x7f, 0x6c, 0xc1, 0x20, + 0x77, 0x68, 0x93, 0x8f, 0x6e, 0x5f, 0xc9, 0xaa, 0x3d, 0xbf, 0x43, 0xe6, 0xb8, 0x63, 0x9c, 0x78, + 0xc3, 0xa7, 0x0e, 0x4c, 0x01, 0xc5, 0x92, 0xf9, 0xcc, 0xcb, 0x30, 0xa2, 0x53, 0x1e, 0xe9, 0xc1, + 0xdc, 0x9f, 0x2b, 0xc2, 0x04, 0x6d, 0xc1, 0x03, 0x1d, 0x88, 0x9b, 0xe9, 0x81, 0x38, 0xee, 0x47, + 0x53, 0xdd, 0x47, 0xe3, 0x8d, 0xe4, 0x68, 0x5c, 0xce, 0x1b, 0x8d, 0x93, 0x1e, 0x83, 0xef, 0xb6, + 0x60, 0x6a, 0xb5, 0xe1, 0xd7, 0x76, 0x13, 0x0f, 0x9b, 0x5e, 0x84, 0x61, 0xba, 0x1d, 0x87, 0xc6, + 0x1b, 0x7f, 0x23, 0xea, 0x83, 0x40, 0x61, 0x9d, 0x4e, 0x2b, 0x76, 0xf3, 0x66, 0x79, 0x39, 0x2b, + 0x58, 0x84, 0x40, 0x61, 0x9d, 0xce, 0xfe, 0x75, 0x0b, 0xce, 0x5d, 0x59, 0x5a, 0x89, 0xa7, 0x62, + 0x2a, 0x5e, 0xc5, 0x45, 0x18, 0x68, 0xd5, 0xb5, 0xa6, 0xc4, 0xea, 0xd5, 0x65, 0xd6, 0x0a, 0x81, + 0x7d, 0xa7, 0xc4, 0x62, 0xb9, 0x09, 0x70, 0x05, 0x57, 0x96, 0xc4, 0xbe, 0x2b, 0xad, 0x29, 0x56, + 0xae, 0x35, 0xe5, 0x09, 0x18, 0xa4, 0xe7, 0x82, 0x5b, 0x93, 0xed, 0xe6, 0x06, 0x5a, 0x0e, 0xc2, + 0x12, 0x67, 0xff, 0x8c, 0x05, 0x53, 0x57, 0xdc, 0x88, 0x1e, 0xda, 0xc9, 0x80, 0x0c, 0xf4, 0xd4, + 0x0e, 0xdd, 0xc8, 0x0f, 0xf6, 0x93, 0x01, 0x19, 0xb0, 0xc2, 0x60, 0x8d, 0x8a, 0x7f, 0xd0, 0x9e, + 0xcb, 0x3c, 0xb4, 0x0b, 0xa6, 0xfd, 0x0a, 0x0b, 0x38, 0x56, 0x14, 0xb4, 0xbf, 0xea, 0x6e, 0xc0, + 0x54, 0x7f, 0xfb, 0x62, 0xe3, 0x56, 0xfd, 0xb5, 0x2c, 0x11, 0x38, 0xa6, 0xb1, 0xff, 0xd0, 0x82, + 0xd9, 0x2b, 0x8d, 0x76, 0x18, 0x91, 0x60, 0x2b, 0xcc, 0xd9, 0x74, 0x9f, 0x87, 0x12, 0x91, 0x8a, + 0x76, 0xf9, 0x94, 0x4c, 0x0a, 0xa2, 0x4a, 0x03, 0xcf, 0xe3, 0x42, 0x28, 0xba, 0x1e, 0x5e, 0x5f, + 0x1e, 0xed, 0xf9, 0xdc, 0x2a, 0x20, 0xa2, 0xd7, 0xa5, 0x07, 0xca, 0x60, 0x2f, 0xee, 0x57, 0x52, + 0x58, 0x9c, 0x51, 0xc2, 0xfe, 0x31, 0x0b, 0x4e, 0xab, 0x0f, 0x7e, 0xc7, 0x7d, 0xa6, 0xfd, 0xd5, + 0x02, 0x8c, 0x5e, 0xdd, 0xd8, 0xa8, 0x5c, 0x21, 0x91, 0x36, 0x2b, 0x3b, 0x9b, 0xcf, 0xb1, 0x66, + 0x05, 0xec, 0x74, 0x47, 0x6c, 0x47, 0x6e, 0x63, 0x8e, 0xc7, 0x5b, 0x9a, 0x2b, 0x7b, 0xd1, 0x8d, + 0xa0, 0x1a, 0x05, 0xae, 0xb7, 0x9d, 0x39, 0xd3, 0xa5, 0xcc, 0x52, 0xcc, 0x93, 0x59, 0xd0, 0xf3, + 0x30, 0xc0, 0x02, 0x3e, 0xc9, 0x41, 0x78, 0x58, 0x5d, 0xb1, 0x18, 0xf4, 0xf0, 0x60, 0xb6, 0x74, + 0x13, 0x97, 0xf9, 0x1f, 0x2c, 0x48, 0xd1, 0x4d, 0x18, 0xde, 0x89, 0xa2, 0xd6, 0x55, 0xe2, 0xd4, + 0x49, 0x20, 0x77, 0xd9, 0xf3, 0x59, 0xbb, 0x2c, 0xed, 0x04, 0x4e, 0x16, 0x6f, 0x4c, 0x31, 0x2c, + 0xc4, 0x3a, 0x1f, 0xbb, 0x0a, 0x10, 0xe3, 0x8e, 0xc9, 0x00, 0x62, 0x6f, 0x40, 0x89, 0x7e, 0xee, + 0x42, 0xc3, 0x75, 0x3a, 0x9b, 0x98, 0x9f, 0x86, 0x92, 0x34, 0x20, 0x87, 0xe2, 0x75, 0x38, 0x3b, + 0x91, 0xa4, 0x7d, 0x39, 0xc4, 0x31, 0xde, 0xde, 0x82, 0x53, 0xcc, 0x1d, 0xd0, 0x89, 0x76, 0x8c, + 0xd9, 0xd7, 0x7d, 0x98, 0x9f, 0x11, 0x37, 0x36, 0xde, 0xe6, 0x69, 0xed, 0x39, 0xe3, 0x88, 0xe4, + 0x18, 0xdf, 0xde, 0xec, 0x6f, 0xf4, 0xc1, 0xc3, 0xe5, 0x6a, 0x7e, 0xc0, 0x92, 0x97, 0x60, 0x84, + 0x0b, 0x82, 0x74, 0xd0, 0x9d, 0x86, 0xa8, 0x57, 0xe9, 0x36, 0x37, 0x34, 0x1c, 0x36, 0x28, 0xd1, + 0x39, 0x28, 0xba, 0x6f, 0x7a, 0xc9, 0xc7, 0x3e, 0xe5, 0xd7, 0xd7, 0x31, 0x85, 0x53, 0x34, 0x95, + 0x29, 0xf9, 0x66, 0xad, 0xd0, 0x4a, 0xae, 0x7c, 0x15, 0xc6, 0xdc, 0xb0, 0x16, 0xba, 0x65, 0x8f, + 0xae, 0x40, 0x6d, 0x0d, 0x2b, 0x6d, 0x02, 0x6d, 0xb4, 0xc2, 0xe2, 0x04, 0xb5, 0x76, 0x72, 0xf4, + 0xf7, 0x2c, 0x97, 0x76, 0x7d, 0x2e, 0x4d, 0x37, 0xf6, 0x16, 0xfb, 0xba, 0x90, 0x29, 0xa9, 0xc5, + 0xc6, 0xce, 0x3f, 0x38, 0xc4, 0x12, 0x47, 0xaf, 0x6a, 0xb5, 0x1d, 0xa7, 0xb5, 0xd0, 0x8e, 0x76, + 0x96, 0xdd, 0xb0, 0xe6, 0xef, 0x91, 0x60, 0x9f, 0xdd, 0xb2, 0x87, 0xe2, 0xab, 0x9a, 0x42, 0x2c, + 0x5d, 0x5d, 0xa8, 0x50, 0x4a, 0x9c, 0x2e, 0x83, 0x16, 0x60, 0x5c, 0x02, 0xab, 0x24, 0x64, 0x9b, + 0xfb, 0x30, 0x63, 0xa3, 0x9e, 0xdf, 0x08, 0xb0, 0x62, 0x92, 0xa4, 0x37, 0x45, 0x57, 0x38, 0x0e, + 0xd1, 0xf5, 0x03, 0x30, 0xea, 0x7a, 0x6e, 0xe4, 0x3a, 0x91, 0xcf, 0x2d, 0x2c, 0xfc, 0x42, 0xcd, + 0x54, 0xc7, 0x65, 0x1d, 0x81, 0x4d, 0x3a, 0xfb, 0x3f, 0xf5, 0xc1, 0x24, 0x1b, 0xb6, 0x77, 0x67, + 0xd8, 0xb7, 0xd3, 0x0c, 0xbb, 0x99, 0x9e, 0x61, 0xc7, 0x21, 0x93, 0xdf, 0xf7, 0x34, 0xfb, 0x34, + 0x94, 0xd4, 0x8b, 0x23, 0xf9, 0xe4, 0xd0, 0xca, 0x79, 0x72, 0xd8, 0xfd, 0x5c, 0x96, 0x4e, 0x5b, + 0xc5, 0x4c, 0xa7, 0xad, 0x2f, 0x5b, 0x10, 0x9b, 0x0c, 0xd0, 0xeb, 0x50, 0x6a, 0xf9, 0xcc, 0x17, + 0x31, 0x90, 0x0e, 0xbe, 0x8f, 0x77, 0xb4, 0x39, 0xf0, 0x98, 0x4d, 0x01, 0xef, 0x85, 0x8a, 0x2c, + 0x8a, 0x63, 0x2e, 0xe8, 0x1a, 0x0c, 0xb6, 0x02, 0x52, 0x8d, 0x58, 0x40, 0x91, 0xde, 0x19, 0xf2, + 0x59, 0xc3, 0x0b, 0x62, 0xc9, 0xc1, 0xfe, 0xcf, 0x16, 0x4c, 0x24, 0x49, 0xd1, 0x07, 0xa1, 0x8f, + 0xdc, 0x25, 0x35, 0xd1, 0xde, 0xcc, 0x43, 0x36, 0x56, 0x3a, 0xf0, 0x0e, 0xa0, 0xff, 0x31, 0x2b, + 0x85, 0xae, 0xc2, 0x20, 0x3d, 0x61, 0xaf, 0xa8, 0xe0, 0x59, 0x8f, 0xe6, 0x9d, 0xd2, 0x4a, 0x54, + 0xe1, 0x8d, 0x13, 0x20, 0x2c, 0x8b, 0x33, 0x4f, 0xa9, 0x5a, 0xab, 0x4a, 0x2f, 0x2f, 0x51, 0xa7, + 0x3b, 0xf6, 0xc6, 0x52, 0x85, 0x13, 0x09, 0x6e, 0xdc, 0x53, 0x4a, 0x02, 0x71, 0xcc, 0xc4, 0xfe, + 0x59, 0x0b, 0x80, 0x3b, 0x86, 0x39, 0xde, 0x36, 0x39, 0x01, 0x3d, 0xf9, 0x32, 0xf4, 0x85, 0x2d, + 0x52, 0xeb, 0xe4, 0x26, 0x1b, 0xb7, 0xa7, 0xda, 0x22, 0xb5, 0x78, 0xc6, 0xd1, 0x7f, 0x98, 0x95, + 0xb6, 0xbf, 0x17, 0x60, 0x2c, 0x26, 0x2b, 0x47, 0xa4, 0x89, 0x9e, 0x35, 0xc2, 0x14, 0x9c, 0x4d, + 0x84, 0x29, 0x28, 0x31, 0x6a, 0x4d, 0x25, 0xfb, 0x69, 0x28, 0x36, 0x9d, 0xbb, 0x42, 0xe7, 0xf6, + 0x74, 0xe7, 0x66, 0x50, 0xfe, 0x73, 0x6b, 0xce, 0x5d, 0x7e, 0x2d, 0x7d, 0x5a, 0xae, 0x90, 0x35, + 0xe7, 0xee, 0x21, 0x77, 0x86, 0x65, 0xbb, 0xf4, 0x75, 0x37, 0x8c, 0x3e, 0xf7, 0x1f, 0xe3, 0xff, + 0x6c, 0xdd, 0xd1, 0x4a, 0x58, 0x5d, 0xae, 0x27, 0x7c, 0x9e, 0x7a, 0xaa, 0xcb, 0xf5, 0x92, 0x75, + 0xb9, 0x5e, 0x0f, 0x75, 0xb9, 0x1e, 0x7a, 0x0b, 0x06, 0x85, 0x4b, 0xa2, 0x08, 0x64, 0x34, 0xdf, + 0x43, 0x7d, 0xc2, 0xa3, 0x91, 0xd7, 0x39, 0x2f, 0xaf, 0xdd, 0x02, 0xda, 0xb5, 0x5e, 0x59, 0x21, + 0xfa, 0xcb, 0x16, 0x8c, 0x89, 0xdf, 0x98, 0xbc, 0xd9, 0x26, 0x61, 0x24, 0xc4, 0xd2, 0xf7, 0xf7, + 0xde, 0x06, 0x51, 0x90, 0x37, 0xe5, 0xfd, 0xf2, 0x9c, 0x31, 0x91, 0x5d, 0x5b, 0x94, 0x68, 0x05, + 0xfa, 0x3b, 0x16, 0x9c, 0x6a, 0x3a, 0x77, 0x79, 0x8d, 0x1c, 0x86, 0x9d, 0xc8, 0xf5, 0x85, 0x69, + 0xff, 0x83, 0xbd, 0x0d, 0x7f, 0xaa, 0x38, 0x6f, 0xa4, 0xb4, 0x3f, 0x9e, 0xca, 0x22, 0xe9, 0xda, + 0xd4, 0xcc, 0x76, 0xcd, 0x6c, 0xc1, 0x90, 0x9c, 0x6f, 0x19, 0xca, 0x8d, 0x65, 0x5d, 0xe6, 0x3e, + 0xb2, 0x47, 0xa8, 0xfe, 0xfc, 0x9f, 0xd6, 0x23, 0xe6, 0xda, 0x03, 0xad, 0xe7, 0xd3, 0x30, 0xa2, + 0xcf, 0xb1, 0x07, 0x5a, 0xd7, 0x9b, 0x30, 0x95, 0x31, 0x97, 0x1e, 0x68, 0x95, 0x77, 0xe0, 0x6c, + 0xee, 0xfc, 0x78, 0x90, 0x15, 0xdb, 0x5f, 0xb5, 0xf4, 0x7d, 0xf0, 0x04, 0x8c, 0x15, 0x4b, 0xa6, + 0xb1, 0xe2, 0x7c, 0xe7, 0x95, 0x93, 0x63, 0xb1, 0x78, 0x43, 0x6f, 0x34, 0xdd, 0xd5, 0xd1, 0x6b, + 0x30, 0xd0, 0xa0, 0x10, 0xe9, 0xd8, 0x6a, 0x77, 0x5f, 0x91, 0xb1, 0x30, 0xc9, 0xe0, 0x21, 0x16, + 0x1c, 0xec, 0x5f, 0xb0, 0xa0, 0xef, 0x04, 0x7a, 0x02, 0x9b, 0x3d, 0xf1, 0x6c, 0x2e, 0x6b, 0x11, + 0xd3, 0x79, 0x0e, 0x3b, 0x77, 0x56, 0xee, 0x46, 0xc4, 0x0b, 0xd9, 0x89, 0x9c, 0xd9, 0x31, 0x3f, + 0x69, 0xc1, 0xd4, 0x75, 0xdf, 0xa9, 0x2f, 0x3a, 0x0d, 0xc7, 0xab, 0x91, 0xa0, 0xec, 0x6d, 0x1f, + 0xc9, 0x2b, 0xbb, 0xd0, 0xd5, 0x2b, 0x7b, 0x49, 0x3a, 0x35, 0xf5, 0xe5, 0x8f, 0x1f, 0x95, 0xa4, + 0x93, 0x81, 0x5b, 0x0c, 0xf7, 0xdb, 0x1d, 0x40, 0x7a, 0x2b, 0xc5, 0x1b, 0x19, 0x0c, 0x83, 0x2e, + 0x6f, 0xaf, 0x18, 0xc4, 0x27, 0xb3, 0x25, 0xdc, 0xd4, 0xe7, 0x69, 0xaf, 0x3f, 0x38, 0x00, 0x4b, + 0x46, 0xf6, 0x4b, 0x90, 0xf9, 0xd0, 0xbe, 0xbb, 0x5e, 0xc2, 0xfe, 0x28, 0x4c, 0xb2, 0x92, 0x47, + 0xd4, 0x0c, 0xd8, 0x09, 0x6d, 0x6a, 0x46, 0xd0, 0x40, 0xfb, 0xf3, 0x16, 0x8c, 0xaf, 0x27, 0x62, + 0xa9, 0x5d, 0x64, 0xf6, 0xd7, 0x0c, 0x25, 0x7e, 0x95, 0x41, 0xb1, 0xc0, 0x1e, 0xbb, 0x92, 0xeb, + 0x4f, 0x2d, 0x88, 0x63, 0x5f, 0x9c, 0x80, 0xf8, 0xb6, 0x64, 0x88, 0x6f, 0x99, 0x82, 0xac, 0x6a, + 0x4e, 0x9e, 0xf4, 0x86, 0xae, 0xa9, 0xa8, 0x50, 0x1d, 0x64, 0xd8, 0x98, 0x0d, 0x9f, 0x8a, 0x63, + 0x66, 0xe8, 0x28, 0x19, 0x27, 0xca, 0xfe, 0xad, 0x02, 0x20, 0x45, 0xdb, 0x73, 0xd4, 0xaa, 0x74, + 0x89, 0xe3, 0x89, 0x5a, 0xb5, 0x07, 0x88, 0x79, 0x10, 0x04, 0x8e, 0x17, 0x72, 0xb6, 0xae, 0x50, + 0xeb, 0x1d, 0xcd, 0x3d, 0x61, 0x46, 0x54, 0x89, 0xae, 0xa7, 0xb8, 0xe1, 0x8c, 0x1a, 0x34, 0xcf, + 0x90, 0xfe, 0x5e, 0x3d, 0x43, 0x06, 0xba, 0xbc, 0x83, 0xfb, 0x8a, 0x05, 0xa3, 0xaa, 0x9b, 0xde, + 0x21, 0x5e, 0xea, 0xaa, 0x3d, 0x39, 0x1b, 0x68, 0x45, 0x6b, 0x32, 0x3b, 0x58, 0xbe, 0x93, 0xbd, + 0x67, 0x74, 0x1a, 0xee, 0x5b, 0x44, 0x45, 0x39, 0x9c, 0x15, 0xef, 0x13, 0x05, 0xf4, 0xf0, 0x60, + 0x76, 0x54, 0xfd, 0xe3, 0x51, 0x9c, 0xe3, 0x22, 0x74, 0x4b, 0x1e, 0x4f, 0x4c, 0x45, 0xf4, 0x22, + 0xf4, 0xb7, 0x76, 0x9c, 0x90, 0x24, 0x5e, 0xf3, 0xf4, 0x57, 0x28, 0xf0, 0xf0, 0x60, 0x76, 0x4c, + 0x15, 0x60, 0x10, 0xcc, 0xa9, 0x7b, 0x8f, 0x05, 0x96, 0x9e, 0x9c, 0x5d, 0x63, 0x81, 0xfd, 0xb1, + 0x05, 0x7d, 0xeb, 0x7e, 0xfd, 0x24, 0xb6, 0x80, 0x57, 0x8d, 0x2d, 0xe0, 0x91, 0xbc, 0x00, 0xfb, + 0xb9, 0xab, 0x7f, 0x35, 0xb1, 0xfa, 0xcf, 0xe7, 0x72, 0xe8, 0xbc, 0xf0, 0x9b, 0x30, 0xcc, 0xc2, + 0xf6, 0x8b, 0x97, 0x4b, 0xcf, 0x1b, 0x0b, 0x7e, 0x36, 0xb1, 0xe0, 0xc7, 0x35, 0x52, 0x6d, 0xa5, + 0x3f, 0x05, 0x83, 0xe2, 0x29, 0x4c, 0xf2, 0x59, 0xa8, 0xa0, 0xc5, 0x12, 0x6f, 0xff, 0x78, 0x11, + 0x8c, 0x34, 0x01, 0xe8, 0x97, 0x2c, 0x98, 0x0b, 0xb8, 0x8b, 0x6c, 0x7d, 0xb9, 0x1d, 0xb8, 0xde, + 0x76, 0xb5, 0xb6, 0x43, 0xea, 0xed, 0x86, 0xeb, 0x6d, 0x97, 0xb7, 0x3d, 0x5f, 0x81, 0x57, 0xee, + 0x92, 0x5a, 0x9b, 0x99, 0xdd, 0xba, 0xe4, 0x24, 0x50, 0xae, 0xe6, 0xcf, 0xdd, 0x3b, 0x98, 0x9d, + 0xc3, 0x47, 0xe2, 0x8d, 0x8f, 0xd8, 0x16, 0xf4, 0xeb, 0x16, 0xcc, 0xf3, 0xe8, 0xf9, 0xbd, 0xb7, + 0xbf, 0xc3, 0x6d, 0xb9, 0x22, 0x59, 0xc5, 0x4c, 0x36, 0x48, 0xd0, 0x5c, 0xfc, 0x80, 0xe8, 0xd0, + 0xf9, 0xca, 0xd1, 0xea, 0xc2, 0x47, 0x6d, 0x9c, 0xfd, 0x8f, 0x8b, 0x30, 0x2a, 0x62, 0x46, 0x89, + 0x33, 0xe0, 0x45, 0x63, 0x4a, 0x3c, 0x9a, 0x98, 0x12, 0x93, 0x06, 0xf1, 0xf1, 0x6c, 0xff, 0x21, + 0x4c, 0xd2, 0xcd, 0xf9, 0x2a, 0x71, 0x82, 0x68, 0x93, 0x38, 0xdc, 0xe1, 0xab, 0x78, 0xe4, 0xdd, + 0x5f, 0xe9, 0x27, 0xaf, 0x27, 0x99, 0xe1, 0x34, 0xff, 0x6f, 0xa7, 0x33, 0xc7, 0x83, 0x89, 0x54, + 0xd8, 0xaf, 0x8f, 0x41, 0x49, 0xbd, 0xe3, 0x10, 0x9b, 0x4e, 0xe7, 0xe8, 0x79, 0x49, 0x0e, 0x5c, + 0xfd, 0x15, 0xbf, 0x21, 0x8a, 0xd9, 0xd9, 0x7f, 0xaf, 0x60, 0x54, 0xc8, 0x07, 0x71, 0x1d, 0x86, + 0x9c, 0x30, 0x74, 0xb7, 0x3d, 0x52, 0xef, 0xa4, 0xa1, 0x4c, 0x55, 0xc3, 0xde, 0xd2, 0x2c, 0x88, + 0x92, 0x58, 0xf1, 0x40, 0x57, 0xb9, 0x5b, 0xdd, 0x1e, 0xe9, 0xa4, 0x9e, 0x4c, 0x71, 0x03, 0xe9, + 0x78, 0xb7, 0x47, 0xb0, 0x28, 0x8f, 0x3e, 0xc1, 0xfd, 0x1e, 0xaf, 0x79, 0xfe, 0x1d, 0xef, 0x8a, + 0xef, 0xcb, 0xb8, 0x0c, 0xbd, 0x31, 0x9c, 0x94, 0xde, 0x8e, 0xaa, 0x38, 0x36, 0xb9, 0xf5, 0x16, + 0x47, 0xf3, 0x33, 0xc0, 0xa2, 0x85, 0x9b, 0xcf, 0xa6, 0x43, 0x44, 0x60, 0x5c, 0x04, 0x24, 0x93, + 0x30, 0xd1, 0x77, 0x99, 0x57, 0x39, 0xb3, 0x74, 0xac, 0x48, 0xbf, 0x66, 0xb2, 0xc0, 0x49, 0x9e, + 0xf6, 0x4f, 0x5b, 0xc0, 0x9e, 0x90, 0x9e, 0x80, 0x3c, 0xf2, 0x21, 0x53, 0x1e, 0x99, 0xce, 0xeb, + 0xe4, 0x1c, 0x51, 0xe4, 0x05, 0x3e, 0xb3, 0x2a, 0x81, 0x7f, 0x77, 0x5f, 0x38, 0xab, 0x74, 0xbf, + 0x7f, 0xd8, 0xff, 0xc7, 0xe2, 0x9b, 0x98, 0x7a, 0x65, 0x81, 0x3e, 0x0b, 0x43, 0x35, 0xa7, 0xe5, + 0xd4, 0x78, 0x4e, 0x9b, 0x5c, 0x8d, 0x9e, 0x51, 0x68, 0x6e, 0x49, 0x94, 0xe0, 0x1a, 0x2a, 0x19, + 0xd8, 0x6e, 0x48, 0x82, 0xbb, 0x6a, 0xa5, 0x54, 0x95, 0x33, 0xbb, 0x30, 0x6a, 0x30, 0x7b, 0xa0, + 0xea, 0x8c, 0xcf, 0xf2, 0x23, 0x56, 0x05, 0x62, 0x6c, 0xc2, 0xa4, 0xa7, 0xfd, 0xa7, 0x07, 0x8a, + 0xbc, 0x5c, 0x3e, 0xde, 0xed, 0x10, 0x65, 0xa7, 0x8f, 0xf6, 0x3a, 0x35, 0xc1, 0x06, 0xa7, 0x39, + 0xdb, 0x3f, 0x61, 0xc1, 0x43, 0x3a, 0xa1, 0xf6, 0x00, 0xa6, 0x9b, 0x91, 0x64, 0x19, 0x86, 0xfc, + 0x16, 0x09, 0x9c, 0xc8, 0x0f, 0xc4, 0xa9, 0x71, 0x49, 0x76, 0xfa, 0x0d, 0x01, 0x3f, 0x14, 0x11, + 0xda, 0x25, 0x77, 0x09, 0xc7, 0xaa, 0x24, 0xbd, 0x7d, 0xb2, 0xce, 0x08, 0xc5, 0x53, 0x27, 0xb6, + 0x07, 0x30, 0x4b, 0x7a, 0x88, 0x05, 0xc6, 0xfe, 0x86, 0xc5, 0x27, 0x96, 0xde, 0x74, 0xf4, 0x26, + 0x4c, 0x34, 0x9d, 0xa8, 0xb6, 0xb3, 0x72, 0xb7, 0x15, 0x70, 0x93, 0x93, 0xec, 0xa7, 0xa7, 0xbb, + 0xf5, 0x93, 0xf6, 0x91, 0xb1, 0x2b, 0xe7, 0x5a, 0x82, 0x19, 0x4e, 0xb1, 0x47, 0x9b, 0x30, 0xcc, + 0x60, 0xec, 0x15, 0x5f, 0xd8, 0x49, 0x34, 0xc8, 0xab, 0x4d, 0x39, 0x23, 0xac, 0xc5, 0x7c, 0xb0, + 0xce, 0xd4, 0xfe, 0x72, 0x91, 0xaf, 0x76, 0x26, 0xca, 0x3f, 0x05, 0x83, 0x2d, 0xbf, 0xbe, 0x54, + 0x5e, 0xc6, 0x62, 0x14, 0xd4, 0x31, 0x52, 0xe1, 0x60, 0x2c, 0xf1, 0xe8, 0x12, 0x0c, 0x89, 0x9f, + 0xd2, 0x44, 0xc8, 0xf6, 0x66, 0x41, 0x17, 0x62, 0x85, 0x45, 0xcf, 0x01, 0xb4, 0x02, 0x7f, 0xcf, + 0xad, 0xb3, 0xe8, 0x12, 0x45, 0xd3, 0x8f, 0xa8, 0xa2, 0x30, 0x58, 0xa3, 0x42, 0xaf, 0xc0, 0x68, + 0xdb, 0x0b, 0xb9, 0x38, 0xa2, 0xc5, 0x92, 0x55, 0x1e, 0x2e, 0x37, 0x75, 0x24, 0x36, 0x69, 0xd1, + 0x02, 0x0c, 0x44, 0x0e, 0xf3, 0x8b, 0xe9, 0xcf, 0x77, 0xf7, 0xdd, 0xa0, 0x14, 0x7a, 0xfa, 0x14, + 0x5a, 0x00, 0x8b, 0x82, 0xe8, 0x63, 0xf2, 0x41, 0x2d, 0xdf, 0xd8, 0x85, 0x9f, 0x7d, 0x6f, 0x87, + 0x80, 0xf6, 0x9c, 0x56, 0xf8, 0xef, 0x1b, 0xbc, 0xd0, 0xcb, 0x00, 0xe4, 0x6e, 0x44, 0x02, 0xcf, + 0x69, 0x28, 0x6f, 0x36, 0x25, 0x17, 0x2c, 0xfb, 0xeb, 0x7e, 0x74, 0x33, 0x24, 0x2b, 0x8a, 0x02, + 0x6b, 0xd4, 0xf6, 0xaf, 0x97, 0x00, 0x62, 0xb9, 0x1d, 0xbd, 0x95, 0xda, 0xb8, 0x9e, 0xe9, 0x2c, + 0xe9, 0x1f, 0xdf, 0xae, 0x85, 0xbe, 0xcf, 0x82, 0x61, 0xa7, 0xd1, 0xf0, 0x6b, 0x0e, 0x8f, 0xf6, + 0x5b, 0xe8, 0xbc, 0x71, 0x8a, 0xfa, 0x17, 0xe2, 0x12, 0xbc, 0x09, 0xcf, 0xcb, 0x19, 0xaa, 0x61, + 0xba, 0xb6, 0x42, 0xaf, 0x18, 0xbd, 0x4f, 0x5e, 0x15, 0x8b, 0x46, 0x57, 0xaa, 0xab, 0x62, 0x89, + 0x9d, 0x11, 0xfa, 0x2d, 0xf1, 0xa6, 0x71, 0x4b, 0xec, 0xcb, 0x7f, 0x31, 0x68, 0x88, 0xaf, 0xdd, + 0x2e, 0x88, 0xa8, 0xa2, 0x47, 0x0f, 0xe8, 0xcf, 0x7f, 0x9e, 0xa7, 0xdd, 0x93, 0xba, 0x44, 0x0e, + 0xf8, 0x34, 0x8c, 0xd7, 0x4d, 0x21, 0x40, 0xcc, 0xc4, 0x27, 0xf3, 0xf8, 0x26, 0x64, 0x86, 0xf8, + 0xd8, 0x4f, 0x20, 0x70, 0x92, 0x31, 0xaa, 0xf0, 0x60, 0x12, 0x65, 0x6f, 0xcb, 0x17, 0x6f, 0x3d, + 0xec, 0xdc, 0xb1, 0xdc, 0x0f, 0x23, 0xd2, 0xa4, 0x94, 0xf1, 0xe9, 0xbe, 0x2e, 0xca, 0x62, 0xc5, + 0x05, 0xbd, 0x06, 0x03, 0xec, 0x7d, 0x56, 0x38, 0x3d, 0x94, 0xaf, 0x71, 0x36, 0xa3, 0xa3, 0xc5, + 0x0b, 0x92, 0xfd, 0x0d, 0xb1, 0xe0, 0x80, 0xae, 0xca, 0xd7, 0x8f, 0x61, 0xd9, 0xbb, 0x19, 0x12, + 0xf6, 0xfa, 0xb1, 0xb4, 0xf8, 0x78, 0xfc, 0xb0, 0x91, 0xc3, 0x33, 0x93, 0xac, 0x19, 0x25, 0xa9, + 0x14, 0x25, 0xfe, 0xcb, 0xdc, 0x6d, 0xd3, 0x90, 0xdf, 0x3c, 0x33, 0xbf, 0x5b, 0xdc, 0x9d, 0xb7, + 0x4c, 0x16, 0x38, 0xc9, 0x93, 0x4a, 0xa4, 0x7c, 0xd5, 0x8b, 0xd7, 0x22, 0xdd, 0xf6, 0x0e, 0x7e, + 0x11, 0x67, 0xa7, 0x11, 0x87, 0x60, 0x51, 0xfe, 0x44, 0xc5, 0x83, 0x19, 0x0f, 0x26, 0x92, 0x4b, + 0xf4, 0x81, 0x8a, 0x23, 0xbf, 0xdf, 0x07, 0x63, 0xe6, 0x94, 0x42, 0xf3, 0x50, 0x12, 0x4c, 0x54, + 0xfe, 0x03, 0xb5, 0x4a, 0xd6, 0x24, 0x02, 0xc7, 0x34, 0x2c, 0xed, 0x05, 0x2b, 0xae, 0xb9, 0x07, + 0xc7, 0x69, 0x2f, 0x14, 0x06, 0x6b, 0x54, 0xf4, 0x62, 0xb5, 0xe9, 0xfb, 0x91, 0x3a, 0x90, 0xd4, + 0xbc, 0x5b, 0x64, 0x50, 0x2c, 0xb0, 0xf4, 0x20, 0xda, 0x25, 0x81, 0x47, 0x1a, 0x66, 0xdc, 0x61, + 0x75, 0x10, 0x5d, 0xd3, 0x91, 0xd8, 0xa4, 0xa5, 0xc7, 0xa9, 0x1f, 0xb2, 0x89, 0x2c, 0xae, 0x6f, + 0xb1, 0xbb, 0x75, 0x95, 0x3f, 0xc0, 0x96, 0x78, 0xf4, 0x51, 0x78, 0x48, 0xc5, 0x56, 0xc2, 0xdc, + 0x9a, 0x21, 0x6b, 0x1c, 0x30, 0xb4, 0x2d, 0x0f, 0x2d, 0x65, 0x93, 0xe1, 0xbc, 0xf2, 0xe8, 0x55, + 0x18, 0x13, 0x22, 0xbe, 0xe4, 0x38, 0x68, 0x7a, 0x18, 0x5d, 0x33, 0xb0, 0x38, 0x41, 0x2d, 0x23, + 0x27, 0x33, 0x29, 0x5b, 0x72, 0x18, 0x4a, 0x47, 0x4e, 0xd6, 0xf1, 0x38, 0x55, 0x02, 0x2d, 0xc0, + 0x38, 0x97, 0xc1, 0x5c, 0x6f, 0x9b, 0x8f, 0x89, 0x78, 0xcc, 0xa5, 0x96, 0xd4, 0x0d, 0x13, 0x8d, + 0x93, 0xf4, 0xe8, 0x25, 0x18, 0x71, 0x82, 0xda, 0x8e, 0x1b, 0x91, 0x5a, 0xd4, 0x0e, 0xf8, 0x2b, + 0x2f, 0xcd, 0x45, 0x6b, 0x41, 0xc3, 0x61, 0x83, 0xd2, 0x7e, 0x0b, 0xa6, 0x32, 0x22, 0x33, 0xd0, + 0x89, 0xe3, 0xb4, 0x5c, 0xf9, 0x4d, 0x09, 0x0f, 0xe7, 0x85, 0x4a, 0x59, 0x7e, 0x8d, 0x46, 0x45, + 0x67, 0x27, 0x8b, 0xe0, 0xa0, 0xa5, 0x6a, 0x54, 0xb3, 0x73, 0x55, 0x22, 0x70, 0x4c, 0x63, 0xff, + 0xb7, 0x02, 0x8c, 0x67, 0xd8, 0x56, 0x58, 0xba, 0xc0, 0xc4, 0x25, 0x25, 0xce, 0x0e, 0x68, 0x06, + 0xe2, 0x2e, 0x1c, 0x21, 0x10, 0x77, 0xb1, 0x5b, 0x20, 0xee, 0xbe, 0xb7, 0x13, 0x88, 0xdb, 0xec, + 0xb1, 0xfe, 0x9e, 0x7a, 0x2c, 0x23, 0x78, 0xf7, 0xc0, 0x11, 0x83, 0x77, 0x1b, 0x9d, 0x3e, 0xd8, + 0x43, 0xa7, 0xff, 0x48, 0x01, 0x26, 0x92, 0xae, 0xa4, 0x27, 0xa0, 0xb7, 0x7d, 0xcd, 0xd0, 0xdb, + 0x5e, 0xea, 0xe5, 0xf1, 0x6d, 0xae, 0x0e, 0x17, 0x27, 0x74, 0xb8, 0xef, 0xed, 0x89, 0x5b, 0x67, + 0x7d, 0xee, 0x5f, 0x2f, 0xc0, 0xe9, 0xcc, 0xd7, 0xbf, 0x27, 0xd0, 0x37, 0x37, 0x8c, 0xbe, 0x79, + 0xb6, 0xe7, 0x87, 0xc9, 0xb9, 0x1d, 0x74, 0x3b, 0xd1, 0x41, 0xf3, 0xbd, 0xb3, 0xec, 0xdc, 0x4b, + 0x5f, 0x2f, 0xc2, 0xf9, 0xcc, 0x72, 0xb1, 0xda, 0x73, 0xd5, 0x50, 0x7b, 0x3e, 0x97, 0x50, 0x7b, + 0xda, 0x9d, 0x4b, 0x1f, 0x8f, 0x1e, 0x54, 0x3c, 0xd0, 0x65, 0x61, 0x06, 0xee, 0x53, 0x07, 0x6a, + 0x3c, 0xd0, 0x55, 0x8c, 0xb0, 0xc9, 0xf7, 0xdb, 0x49, 0xf7, 0xf9, 0xaf, 0x2c, 0x38, 0x9b, 0x39, + 0x36, 0x27, 0xa0, 0xeb, 0x5a, 0x37, 0x75, 0x5d, 0x4f, 0xf5, 0x3c, 0x5b, 0x73, 0x94, 0x5f, 0x3f, + 0xd5, 0x9f, 0xf3, 0x2d, 0xec, 0x26, 0x7f, 0x03, 0x86, 0x9d, 0x5a, 0x8d, 0x84, 0xe1, 0x9a, 0x5f, + 0x57, 0xb1, 0x86, 0x9f, 0x65, 0xf7, 0xac, 0x18, 0x7c, 0x78, 0x30, 0x3b, 0x93, 0x64, 0x11, 0xa3, + 0xb1, 0xce, 0x01, 0x7d, 0x02, 0x86, 0x42, 0x71, 0x6e, 0x8a, 0xb1, 0x7f, 0xbe, 0xc7, 0xce, 0x71, + 0x36, 0x49, 0xc3, 0x0c, 0x86, 0xa4, 0x34, 0x15, 0x8a, 0xa5, 0x19, 0x38, 0xa5, 0x70, 0xac, 0x81, + 0x53, 0x9e, 0x03, 0xd8, 0x53, 0x97, 0x81, 0xa4, 0xfe, 0x41, 0xbb, 0x26, 0x68, 0x54, 0xe8, 0xc3, + 0x30, 0x11, 0xf2, 0x68, 0x81, 0x4b, 0x0d, 0x27, 0x64, 0xef, 0x68, 0xc4, 0x2c, 0x64, 0x01, 0x97, + 0xaa, 0x09, 0x1c, 0x4e, 0x51, 0xa3, 0x55, 0x59, 0x2b, 0x0b, 0x6d, 0xc8, 0x27, 0xe6, 0xc5, 0xb8, + 0x46, 0x91, 0xac, 0xf8, 0x54, 0xb2, 0xfb, 0x59, 0xc7, 0x6b, 0x25, 0xd1, 0x27, 0x00, 0xe8, 0xf4, + 0x11, 0x7a, 0x88, 0xc1, 0xfc, 0xcd, 0x93, 0xee, 0x2a, 0xf5, 0x4c, 0xe7, 0x66, 0xf6, 0xa6, 0x76, + 0x59, 0x31, 0xc1, 0x1a, 0x43, 0xe4, 0xc0, 0x68, 0xfc, 0x2f, 0xce, 0xe5, 0x79, 0x29, 0xb7, 0x86, + 0x24, 0x73, 0xa6, 0xf2, 0x5e, 0xd6, 0x59, 0x60, 0x93, 0xa3, 0xfd, 0x63, 0x83, 0xf0, 0x70, 0x87, + 0x6d, 0x18, 0x2d, 0x98, 0xa6, 0xde, 0xa7, 0x93, 0xf7, 0xf7, 0x99, 0xcc, 0xc2, 0xc6, 0x85, 0x3e, + 0x31, 0xdb, 0x0b, 0x6f, 0x7b, 0xb6, 0xff, 0x90, 0xa5, 0x69, 0x56, 0xb8, 0x53, 0xe9, 0x87, 0x8e, + 0x78, 0xbc, 0x1c, 0xa3, 0xaa, 0x65, 0x2b, 0x43, 0x5f, 0xf1, 0x5c, 0xcf, 0xcd, 0xe9, 0x5d, 0x81, + 0xf1, 0x55, 0x0b, 0x90, 0xd0, 0xac, 0x90, 0xba, 0x5a, 0x4b, 0x42, 0x95, 0x71, 0xe5, 0xa8, 0xdf, + 0xbf, 0x90, 0xe2, 0xc4, 0x7b, 0xe2, 0x65, 0x79, 0x0e, 0xa4, 0x09, 0xba, 0xf6, 0x49, 0x46, 0xf3, + 0xd0, 0x47, 0x59, 0x20, 0x5d, 0xf7, 0x2d, 0x21, 0xfc, 0x88, 0xb5, 0xf6, 0xa2, 0x08, 0xa2, 0xab, + 0xe0, 0x54, 0xca, 0xcd, 0x6c, 0xae, 0x4e, 0x84, 0x0d, 0x56, 0x27, 0x7b, 0xf5, 0x6e, 0xc3, 0x43, + 0x39, 0x5d, 0xf6, 0x40, 0x6f, 0xe0, 0xbf, 0x69, 0xc1, 0xb9, 0x8e, 0x11, 0x61, 0xbe, 0x05, 0x65, + 0x43, 0xfb, 0x73, 0x16, 0x64, 0x0f, 0xb6, 0xe1, 0x51, 0x36, 0x0f, 0xa5, 0x5a, 0x22, 0xeb, 0x60, + 0x1c, 0x1b, 0x41, 0x65, 0x1c, 0x8c, 0x69, 0x0c, 0xc7, 0xb1, 0x42, 0x57, 0xc7, 0xb1, 0x5f, 0xb1, + 0x20, 0xb5, 0xbf, 0x9f, 0x80, 0xa0, 0x51, 0x36, 0x05, 0x8d, 0xc7, 0x7b, 0xe9, 0xcd, 0x1c, 0x19, + 0xe3, 0x8f, 0xc6, 0xe1, 0x4c, 0xce, 0x8b, 0xbc, 0x3d, 0x98, 0xdc, 0xae, 0x11, 0xf3, 0x71, 0x75, + 0xa7, 0xa0, 0x43, 0x1d, 0x5f, 0x62, 0xf3, 0x64, 0x8f, 0x29, 0x12, 0x9c, 0xae, 0x02, 0x7d, 0xce, + 0x82, 0x53, 0xce, 0x9d, 0x70, 0x85, 0x0a, 0x8c, 0x6e, 0x6d, 0xb1, 0xe1, 0xd7, 0x76, 0xe9, 0x69, + 0x2c, 0x17, 0xc2, 0x0b, 0x99, 0x4a, 0xbc, 0xdb, 0xd5, 0x14, 0xbd, 0x51, 0x3d, 0x4b, 0xed, 0x9b, + 0x45, 0x85, 0x33, 0xeb, 0x42, 0x58, 0x64, 0x4f, 0xa0, 0xd7, 0xd1, 0x0e, 0xcf, 0xff, 0xb3, 0x9e, + 0x4e, 0x72, 0x09, 0x48, 0x62, 0xb0, 0xe2, 0x83, 0x3e, 0x05, 0xa5, 0x6d, 0xf9, 0xd2, 0x37, 0x43, + 0xc2, 0x8a, 0x3b, 0xb2, 0xf3, 0xfb, 0x67, 0x6e, 0x89, 0x57, 0x44, 0x38, 0x66, 0x8a, 0x5e, 0x85, + 0xa2, 0xb7, 0x15, 0x76, 0xca, 0x8e, 0x9b, 0x70, 0xb9, 0xe4, 0x41, 0x36, 0xd6, 0x57, 0xab, 0x98, + 0x16, 0x44, 0x57, 0xa1, 0x18, 0x6c, 0xd6, 0x85, 0x06, 0x3a, 0x73, 0x91, 0xe2, 0xc5, 0xe5, 0x9c, + 0x56, 0x31, 0x4e, 0x78, 0x71, 0x19, 0x53, 0x16, 0xa8, 0x02, 0xfd, 0xec, 0x19, 0x9b, 0x90, 0x67, + 0x32, 0x6f, 0x6e, 0x1d, 0x9e, 0x83, 0xf2, 0x48, 0x1c, 0x8c, 0x00, 0x73, 0x46, 0x68, 0x03, 0x06, + 0x6a, 0x2c, 0x93, 0xaa, 0x10, 0x60, 0xde, 0x97, 0xa9, 0x6b, 0xee, 0x90, 0x62, 0x56, 0xa8, 0x5e, + 0x19, 0x05, 0x16, 0xbc, 0x18, 0x57, 0xd2, 0xda, 0xd9, 0x0a, 0x45, 0xa6, 0xf1, 0x6c, 0xae, 0x1d, + 0x32, 0x27, 0x0b, 0xae, 0x8c, 0x02, 0x0b, 0x5e, 0xe8, 0x65, 0x28, 0x6c, 0xd5, 0xc4, 0x13, 0xb5, + 0x4c, 0xa5, 0xb3, 0x19, 0x27, 0x65, 0x71, 0xe0, 0xde, 0xc1, 0x6c, 0x61, 0x75, 0x09, 0x17, 0xb6, + 0x6a, 0x68, 0x1d, 0x06, 0xb7, 0x78, 0x64, 0x05, 0xa1, 0x57, 0x7e, 0x32, 0x3b, 0xe8, 0x43, 0x2a, + 0xf8, 0x02, 0x7f, 0xee, 0x24, 0x10, 0x58, 0x32, 0x61, 0xc9, 0x08, 0x54, 0x84, 0x08, 0x11, 0xa0, + 0x6e, 0xee, 0x68, 0x51, 0x3d, 0xb8, 0x7c, 0x19, 0xc7, 0x99, 0xc0, 0x1a, 0x47, 0x3a, 0xab, 0x9d, + 0xb7, 0xda, 0x01, 0x8b, 0x02, 0x2e, 0x22, 0x19, 0x65, 0xce, 0xea, 0x05, 0x49, 0xd4, 0x69, 0x56, + 0x2b, 0x22, 0x1c, 0x33, 0x45, 0xbb, 0x30, 0xba, 0x17, 0xb6, 0x76, 0x88, 0x5c, 0xd2, 0x2c, 0xb0, + 0x51, 0x8e, 0x7c, 0x74, 0x4b, 0x10, 0xba, 0x41, 0xd4, 0x76, 0x1a, 0xa9, 0x5d, 0x88, 0xc9, 0xb2, + 0xb7, 0x74, 0x66, 0xd8, 0xe4, 0x4d, 0xbb, 0xff, 0xcd, 0xb6, 0xbf, 0xb9, 0x1f, 0x11, 0x11, 0x57, + 0x2e, 0xb3, 0xfb, 0x5f, 0xe7, 0x24, 0xe9, 0xee, 0x17, 0x08, 0x2c, 0x99, 0xa0, 0x5b, 0xa2, 0x7b, + 0xd8, 0xee, 0x39, 0x91, 0x1f, 0xfc, 0x75, 0x41, 0x12, 0xe5, 0x74, 0x0a, 0xdb, 0x2d, 0x63, 0x56, + 0x6c, 0x97, 0x6c, 0xed, 0xf8, 0x91, 0xef, 0x25, 0x76, 0xe8, 0xc9, 0xfc, 0x5d, 0xb2, 0x92, 0x41, + 0x9f, 0xde, 0x25, 0xb3, 0xa8, 0x70, 0x66, 0x5d, 0xa8, 0x0e, 0x63, 0x2d, 0x3f, 0x88, 0xee, 0xf8, + 0x81, 0x9c, 0x5f, 0xa8, 0x83, 0x5e, 0xcc, 0xa0, 0x14, 0x35, 0xb2, 0x90, 0x8d, 0x26, 0x06, 0x27, + 0x78, 0xa2, 0x8f, 0xc0, 0x60, 0x58, 0x73, 0x1a, 0xa4, 0x7c, 0x63, 0x7a, 0x2a, 0xff, 0xf8, 0xa9, + 0x72, 0x92, 0x9c, 0xd9, 0xc5, 0x03, 0x63, 0x70, 0x12, 0x2c, 0xd9, 0xa1, 0x55, 0xe8, 0x67, 0xc9, + 0xe6, 0x58, 0x10, 0xc4, 0x9c, 0x18, 0xb6, 0x29, 0x07, 0x78, 0xbe, 0x37, 0x31, 0x30, 0xe6, 0xc5, + 0xe9, 0x1a, 0x10, 0xd7, 0x43, 0x3f, 0x9c, 0x3e, 0x9d, 0xbf, 0x06, 0xc4, 0xad, 0xf2, 0x46, 0xb5, + 0xd3, 0x1a, 0x50, 0x44, 0x38, 0x66, 0x4a, 0x77, 0x66, 0xba, 0x9b, 0x9e, 0xe9, 0xe0, 0xb9, 0x95, + 0xbb, 0x97, 0xb2, 0x9d, 0x99, 0xee, 0xa4, 0x94, 0x85, 0xfd, 0xbb, 0x83, 0x69, 0x99, 0x85, 0x29, + 0x14, 0xbe, 0xc7, 0x4a, 0xd9, 0x9a, 0xdf, 0xdf, 0xab, 0x7e, 0xf3, 0x18, 0xaf, 0x42, 0x9f, 0xb3, + 0xe0, 0x4c, 0x2b, 0xf3, 0x43, 0x84, 0x00, 0xd0, 0x9b, 0x9a, 0x94, 0x7f, 0xba, 0x0a, 0x98, 0x99, + 0x8d, 0xc7, 0x39, 0x35, 0x25, 0xaf, 0x9b, 0xc5, 0xb7, 0x7d, 0xdd, 0x5c, 0x83, 0xa1, 0x1a, 0xbf, + 0x8a, 0x74, 0xcc, 0x2c, 0x9e, 0xbc, 0x7b, 0x33, 0x51, 0x42, 0xdc, 0x61, 0xb6, 0xb0, 0x62, 0x81, + 0x7e, 0xd8, 0x82, 0x73, 0xc9, 0xa6, 0x63, 0xc2, 0xd0, 0x22, 0xca, 0x26, 0xd7, 0x65, 0xac, 0x8a, + 0xef, 0x4f, 0xc9, 0xff, 0x06, 0xf1, 0x61, 0x37, 0x02, 0xdc, 0xb9, 0x32, 0xb4, 0x9c, 0xa1, 0x4c, + 0x19, 0x30, 0x0d, 0x48, 0x3d, 0x28, 0x54, 0x5e, 0x80, 0x91, 0xa6, 0xdf, 0xf6, 0x22, 0xe1, 0xe8, + 0x25, 0x9c, 0x4e, 0x98, 0xb3, 0xc5, 0x9a, 0x06, 0xc7, 0x06, 0x55, 0x42, 0x0d, 0x33, 0x74, 0xdf, + 0x6a, 0x98, 0x37, 0x60, 0xc4, 0xd3, 0x3c, 0x93, 0x85, 0x3c, 0x70, 0x31, 0x3f, 0x42, 0xae, 0xee, + 0xc7, 0xcc, 0x5b, 0xa9, 0x43, 0xb0, 0xc1, 0xed, 0x64, 0x3d, 0xc0, 0xbe, 0x64, 0x65, 0x08, 0xf5, + 0x5c, 0x15, 0xf3, 0x41, 0x53, 0x15, 0x73, 0x31, 0xa9, 0x8a, 0x49, 0x19, 0x0f, 0x0c, 0x2d, 0x4c, + 0xef, 0x09, 0x80, 0x7a, 0x8d, 0xb2, 0x69, 0x37, 0xe0, 0x42, 0xb7, 0x63, 0x89, 0x79, 0xfc, 0xd5, + 0x95, 0xa9, 0x38, 0xf6, 0xf8, 0xab, 0x97, 0x97, 0x31, 0xc3, 0xf4, 0x1a, 0xbf, 0xc9, 0xfe, 0x2f, + 0x16, 0x14, 0x2b, 0x7e, 0xfd, 0x04, 0x2e, 0xbc, 0x1f, 0x32, 0x2e, 0xbc, 0x0f, 0x67, 0x1f, 0x88, + 0xf5, 0x5c, 0xd3, 0xc7, 0x4a, 0xc2, 0xf4, 0x71, 0x2e, 0x8f, 0x41, 0x67, 0x43, 0xc7, 0x4f, 0x16, + 0x61, 0xb8, 0xe2, 0xd7, 0x95, 0xbb, 0xfd, 0x3f, 0xbd, 0x1f, 0x77, 0xfb, 0xdc, 0x34, 0x16, 0x1a, + 0x67, 0xe6, 0x28, 0x28, 0x5f, 0x1a, 0x7f, 0x8b, 0x79, 0xdd, 0xdf, 0x26, 0xee, 0xf6, 0x4e, 0x44, + 0xea, 0xc9, 0xcf, 0x39, 0x39, 0xaf, 0xfb, 0xdf, 0x2d, 0xc0, 0x78, 0xa2, 0x76, 0xd4, 0x80, 0xd1, + 0x86, 0xae, 0x58, 0x17, 0xf3, 0xf4, 0xbe, 0x74, 0xf2, 0xc2, 0x6b, 0x59, 0x03, 0x61, 0x93, 0x39, + 0x9a, 0x03, 0x50, 0x96, 0x66, 0xa9, 0x5e, 0x65, 0x52, 0xbf, 0x32, 0x45, 0x87, 0x58, 0xa3, 0x40, + 0x2f, 0xc2, 0x70, 0xe4, 0xb7, 0xfc, 0x86, 0xbf, 0xbd, 0x7f, 0x8d, 0xc8, 0xd0, 0x5e, 0xca, 0x17, + 0x71, 0x23, 0x46, 0x61, 0x9d, 0x0e, 0xdd, 0x85, 0x49, 0xc5, 0xa4, 0x7a, 0x0c, 0xc6, 0x06, 0xa6, + 0x55, 0x58, 0x4f, 0x72, 0xc4, 0xe9, 0x4a, 0xec, 0x9f, 0x29, 0xf2, 0x2e, 0xf6, 0x22, 0xf7, 0xdd, + 0xd5, 0xf0, 0xce, 0x5e, 0x0d, 0x5f, 0xb7, 0x60, 0x82, 0xd6, 0xce, 0x1c, 0xad, 0xe4, 0x31, 0xaf, + 0x62, 0x72, 0x5b, 0x1d, 0x62, 0x72, 0x5f, 0xa4, 0xbb, 0x66, 0xdd, 0x6f, 0x47, 0x42, 0x77, 0xa7, + 0x6d, 0x8b, 0x14, 0x8a, 0x05, 0x56, 0xd0, 0x91, 0x20, 0x10, 0x8f, 0x43, 0x75, 0x3a, 0x12, 0x04, + 0x58, 0x60, 0x65, 0xc8, 0xee, 0xbe, 0xec, 0x90, 0xdd, 0x3c, 0xf2, 0xaa, 0x70, 0xc9, 0x11, 0x02, + 0x97, 0x16, 0x79, 0x55, 0xfa, 0xea, 0xc4, 0x34, 0xf6, 0x57, 0x8b, 0x30, 0x52, 0xf1, 0xeb, 0xb1, + 0x95, 0xf9, 0x05, 0xc3, 0xca, 0x7c, 0x21, 0x61, 0x65, 0x9e, 0xd0, 0x69, 0xdf, 0xb5, 0x29, 0x7f, + 0xb3, 0x6c, 0xca, 0xbf, 0x6c, 0xb1, 0x51, 0x5b, 0x5e, 0xaf, 0x72, 0xbf, 0x3d, 0x74, 0x19, 0x86, + 0xd9, 0x06, 0xc3, 0x5e, 0x23, 0x4b, 0xd3, 0x2b, 0x4b, 0x45, 0xb5, 0x1e, 0x83, 0xb1, 0x4e, 0x83, + 0x2e, 0xc1, 0x50, 0x48, 0x9c, 0xa0, 0xb6, 0xa3, 0x76, 0x57, 0x61, 0x27, 0xe5, 0x30, 0xac, 0xb0, + 0xe8, 0xf5, 0x38, 0xe8, 0x67, 0x31, 0xff, 0x75, 0xa3, 0xde, 0x1e, 0xbe, 0x44, 0xf2, 0x23, 0x7d, + 0xda, 0xb7, 0x01, 0xa5, 0xe9, 0x7b, 0x08, 0x4b, 0x37, 0x6b, 0x86, 0xa5, 0x2b, 0xa5, 0x42, 0xd2, + 0xfd, 0x89, 0x05, 0x63, 0x15, 0xbf, 0x4e, 0x97, 0xee, 0xb7, 0xd3, 0x3a, 0xd5, 0x23, 0x1e, 0x0f, + 0x74, 0x88, 0x78, 0xfc, 0x18, 0xf4, 0x57, 0xfc, 0x7a, 0xb9, 0xd2, 0x29, 0xb4, 0x80, 0xfd, 0x37, + 0x2c, 0x18, 0xac, 0xf8, 0xf5, 0x13, 0x30, 0x0b, 0x7c, 0xd0, 0x34, 0x0b, 0x3c, 0x94, 0x33, 0x6f, + 0x72, 0x2c, 0x01, 0x7f, 0xad, 0x0f, 0x46, 0x69, 0x3b, 0xfd, 0x6d, 0x39, 0x94, 0x46, 0xb7, 0x59, + 0x3d, 0x74, 0x1b, 0x95, 0xc2, 0xfd, 0x46, 0xc3, 0xbf, 0x93, 0x1c, 0xd6, 0x55, 0x06, 0xc5, 0x02, + 0x8b, 0x9e, 0x81, 0xa1, 0x56, 0x40, 0xf6, 0x5c, 0x5f, 0x88, 0xb7, 0x9a, 0x91, 0xa5, 0x22, 0xe0, + 0x58, 0x51, 0xd0, 0x6b, 0x61, 0xe8, 0x7a, 0xf4, 0x28, 0xaf, 0xf9, 0x5e, 0x9d, 0x6b, 0xce, 0x8b, + 0x22, 0x2d, 0x87, 0x06, 0xc7, 0x06, 0x15, 0xba, 0x0d, 0x25, 0xf6, 0x9f, 0x6d, 0x3b, 0x47, 0x4f, + 0xf0, 0x2a, 0x12, 0xfe, 0x09, 0x06, 0x38, 0xe6, 0x85, 0x9e, 0x03, 0x88, 0x64, 0x68, 0xfb, 0x50, + 0x04, 0x5a, 0x53, 0x57, 0x01, 0x15, 0xf4, 0x3e, 0xc4, 0x1a, 0x15, 0x7a, 0x1a, 0x4a, 0x91, 0xe3, + 0x36, 0xae, 0xbb, 0x1e, 0x09, 0x99, 0x46, 0xbc, 0x28, 0xf3, 0xee, 0x09, 0x20, 0x8e, 0xf1, 0x54, + 0x14, 0x63, 0x41, 0x38, 0x78, 0x7a, 0xe8, 0x21, 0x46, 0xcd, 0x44, 0xb1, 0xeb, 0x0a, 0x8a, 0x35, + 0x0a, 0xb4, 0x03, 0x8f, 0xb8, 0x1e, 0x4b, 0x61, 0x41, 0xaa, 0xbb, 0x6e, 0x6b, 0xe3, 0x7a, 0xf5, + 0x16, 0x09, 0xdc, 0xad, 0xfd, 0x45, 0xa7, 0xb6, 0x4b, 0x3c, 0x99, 0xba, 0xf3, 0x71, 0xd1, 0xc4, + 0x47, 0xca, 0x1d, 0x68, 0x71, 0x47, 0x4e, 0xf6, 0xf3, 0x6c, 0xbe, 0xdf, 0xa8, 0xa2, 0xf7, 0x1a, + 0x5b, 0xc7, 0x19, 0x7d, 0xeb, 0x38, 0x3c, 0x98, 0x1d, 0xb8, 0x51, 0xd5, 0x62, 0x48, 0xbc, 0x04, + 0xa7, 0x2b, 0x7e, 0xbd, 0xe2, 0x07, 0xd1, 0xaa, 0x1f, 0xdc, 0x71, 0x82, 0xba, 0x9c, 0x5e, 0xb3, + 0x32, 0x8a, 0x06, 0xdd, 0x3f, 0xfb, 0xf9, 0xee, 0x62, 0x44, 0xc8, 0x78, 0x9e, 0x49, 0x6c, 0x47, + 0x7c, 0xfb, 0x55, 0x63, 0xb2, 0x83, 0x4a, 0x02, 0x73, 0xc5, 0x89, 0x08, 0xba, 0xc1, 0x92, 0x5b, + 0xc7, 0xc7, 0xa8, 0x28, 0xfe, 0x94, 0x96, 0xdc, 0x3a, 0x46, 0x66, 0x9e, 0xbb, 0x66, 0x79, 0xfb, + 0xb3, 0xa2, 0x12, 0x7e, 0x07, 0xe7, 0xfe, 0x75, 0xbd, 0x64, 0xb7, 0x95, 0x59, 0x22, 0x0a, 0xf9, + 0xe9, 0x05, 0xb8, 0xd5, 0xb3, 0x63, 0x96, 0x08, 0xfb, 0x45, 0x98, 0xa4, 0x57, 0x3f, 0x25, 0x47, + 0xb1, 0x8f, 0xec, 0x1e, 0xcd, 0xe3, 0xbf, 0xf6, 0xb3, 0x73, 0x20, 0x91, 0xfe, 0x04, 0x7d, 0x12, + 0xc6, 0x42, 0x72, 0xdd, 0xf5, 0xda, 0x77, 0xa5, 0xe2, 0xa5, 0xc3, 0x9b, 0xc3, 0xea, 0x8a, 0x4e, + 0xc9, 0xd5, 0xb7, 0x26, 0x0c, 0x27, 0xb8, 0xa1, 0x26, 0x8c, 0xdd, 0x71, 0xbd, 0xba, 0x7f, 0x27, + 0x94, 0xfc, 0x87, 0xf2, 0xb5, 0xb8, 0xb7, 0x39, 0x65, 0xa2, 0x8d, 0x46, 0x75, 0xb7, 0x0d, 0x66, + 0x38, 0xc1, 0x9c, 0xae, 0xb5, 0xa0, 0xed, 0x2d, 0x84, 0x37, 0x43, 0x12, 0x88, 0xe4, 0xea, 0x6c, + 0xad, 0x61, 0x09, 0xc4, 0x31, 0x9e, 0xae, 0x35, 0xf6, 0xe7, 0x4a, 0xe0, 0xb7, 0x79, 0xae, 0x0d, + 0xb1, 0xd6, 0xb0, 0x82, 0x62, 0x8d, 0x82, 0xee, 0x45, 0xec, 0xdf, 0xba, 0xef, 0x61, 0xdf, 0x8f, + 0xe4, 0xee, 0xc5, 0x3c, 0x11, 0x34, 0x38, 0x36, 0xa8, 0xd0, 0x2a, 0xa0, 0xb0, 0xdd, 0x6a, 0x35, + 0x98, 0x33, 0x93, 0xd3, 0x60, 0xac, 0xb8, 0x97, 0x47, 0x91, 0xc7, 0x0a, 0xae, 0xa6, 0xb0, 0x38, + 0xa3, 0x04, 0x3d, 0x96, 0xb6, 0x44, 0x53, 0xfb, 0x59, 0x53, 0xb9, 0xc5, 0xa7, 0xca, 0xdb, 0x29, + 0x71, 0x68, 0x05, 0x06, 0xc3, 0xfd, 0xb0, 0x16, 0x89, 0xd0, 0x8e, 0x39, 0x19, 0xae, 0xaa, 0x8c, + 0x44, 0x4b, 0xb0, 0xc8, 0x8b, 0x60, 0x59, 0x16, 0xd5, 0x60, 0x4a, 0x70, 0x5c, 0xda, 0x71, 0x3c, + 0x95, 0x2f, 0x88, 0xfb, 0x74, 0x5f, 0xbe, 0x77, 0x30, 0x3b, 0x25, 0x6a, 0xd6, 0xd1, 0x87, 0x07, + 0xb3, 0x67, 0x2a, 0x7e, 0x3d, 0x03, 0x83, 0xb3, 0xb8, 0xf1, 0xc9, 0x57, 0xab, 0xf9, 0xcd, 0x56, + 0x25, 0xf0, 0xb7, 0xdc, 0x06, 0xe9, 0x64, 0x35, 0xab, 0x1a, 0x94, 0x62, 0xf2, 0x19, 0x30, 0x9c, + 0xe0, 0x66, 0x7f, 0x96, 0x89, 0x6e, 0x2c, 0x9f, 0x78, 0xd4, 0x0e, 0x08, 0x6a, 0xc2, 0x68, 0x8b, + 0x2d, 0x6e, 0x91, 0x01, 0x43, 0xcc, 0xf5, 0x17, 0x7a, 0xd4, 0xfe, 0xdc, 0xa1, 0x27, 0x9e, 0xe9, + 0x19, 0x55, 0xd1, 0xd9, 0x61, 0x93, 0xbb, 0xfd, 0x6f, 0xce, 0xb2, 0xc3, 0xbf, 0xca, 0x55, 0x3a, + 0x83, 0xe2, 0x09, 0x89, 0xb8, 0x45, 0xce, 0xe4, 0xeb, 0x16, 0xe3, 0x61, 0x11, 0xcf, 0x50, 0xb0, + 0x2c, 0x8b, 0x3e, 0x01, 0x63, 0xf4, 0x52, 0xa6, 0x0e, 0xe0, 0x70, 0xfa, 0x54, 0x7e, 0xa8, 0x0f, + 0x45, 0xa5, 0x67, 0xc7, 0xd1, 0x0b, 0xe3, 0x04, 0x33, 0xf4, 0x3a, 0xf3, 0x44, 0x92, 0xac, 0x0b, + 0xbd, 0xb0, 0xd6, 0x9d, 0x8e, 0x24, 0x5b, 0x8d, 0x09, 0x6a, 0xc3, 0x54, 0x3a, 0x97, 0x5e, 0x38, + 0x6d, 0xe7, 0x4b, 0xb7, 0xe9, 0x74, 0x78, 0x71, 0x1a, 0x93, 0x34, 0x2e, 0xc4, 0x59, 0xfc, 0xd1, + 0x75, 0x18, 0x15, 0x49, 0xb5, 0xc5, 0xcc, 0x2d, 0x1a, 0x2a, 0xcf, 0x51, 0xac, 0x23, 0x0f, 0x93, + 0x00, 0x6c, 0x16, 0x46, 0xdb, 0x70, 0x4e, 0x4b, 0x72, 0x75, 0x25, 0x70, 0x98, 0xdf, 0x82, 0xcb, + 0xb6, 0x53, 0x4d, 0x2c, 0x79, 0xf4, 0xde, 0xc1, 0xec, 0xb9, 0x8d, 0x4e, 0x84, 0xb8, 0x33, 0x1f, + 0x74, 0x03, 0x4e, 0xf3, 0x87, 0xea, 0xcb, 0xc4, 0xa9, 0x37, 0x5c, 0x4f, 0xc9, 0x3d, 0x7c, 0xc9, + 0x9f, 0xbd, 0x77, 0x30, 0x7b, 0x7a, 0x21, 0x8b, 0x00, 0x67, 0x97, 0x43, 0x1f, 0x84, 0x52, 0xdd, + 0x0b, 0x45, 0x1f, 0x0c, 0x18, 0x79, 0xc4, 0x4a, 0xcb, 0xeb, 0x55, 0xf5, 0xfd, 0xf1, 0x1f, 0x1c, + 0x17, 0x40, 0xdb, 0x5c, 0x2d, 0xae, 0x94, 0x35, 0x83, 0xa9, 0x40, 0x5d, 0x49, 0x7d, 0xa6, 0xf1, + 0x54, 0x95, 0xdb, 0x83, 0xd4, 0x0b, 0x0e, 0xe3, 0x15, 0xab, 0xc1, 0x18, 0xbd, 0x06, 0x48, 0xc4, + 0xab, 0x5f, 0xa8, 0xb1, 0xf4, 0x2a, 0xcc, 0x8a, 0x30, 0x64, 0x3e, 0x9e, 0xac, 0xa6, 0x28, 0x70, + 0x46, 0x29, 0x74, 0x95, 0xee, 0x2a, 0x3a, 0x54, 0xec, 0x5a, 0x2a, 0xeb, 0xe3, 0x32, 0x69, 0x05, + 0x84, 0xf9, 0x61, 0x99, 0x1c, 0x71, 0xa2, 0x1c, 0xaa, 0xc3, 0x23, 0x4e, 0x3b, 0xf2, 0x99, 0xc5, + 0xc1, 0x24, 0xdd, 0xf0, 0x77, 0x89, 0xc7, 0x8c, 0x7d, 0x43, 0x8b, 0x17, 0xa8, 0x60, 0xb5, 0xd0, + 0x81, 0x0e, 0x77, 0xe4, 0x42, 0x05, 0x62, 0x95, 0xe6, 0x19, 0xcc, 0xf0, 0x63, 0x19, 0xa9, 0x9e, + 0x5f, 0x84, 0xe1, 0x1d, 0x3f, 0x8c, 0xd6, 0x49, 0x74, 0xc7, 0x0f, 0x76, 0x45, 0x18, 0xdd, 0x38, + 0x28, 0x79, 0x8c, 0xc2, 0x3a, 0x1d, 0xbd, 0xf1, 0x32, 0x57, 0x94, 0xf2, 0x32, 0xf3, 0x02, 0x18, + 0x8a, 0xf7, 0x98, 0xab, 0x1c, 0x8c, 0x25, 0x5e, 0x92, 0x96, 0x2b, 0x4b, 0xcc, 0xa2, 0x9f, 0x20, + 0x2d, 0x57, 0x96, 0xb0, 0xc4, 0xd3, 0xe9, 0x1a, 0xee, 0x38, 0x01, 0xa9, 0x04, 0x7e, 0x8d, 0x84, + 0x5a, 0x28, 0xfc, 0x87, 0x79, 0x90, 0x60, 0x3a, 0x5d, 0xab, 0x59, 0x04, 0x38, 0xbb, 0x1c, 0x22, + 0xe9, 0x04, 0x6f, 0x63, 0xf9, 0xa6, 0x98, 0xb4, 0x3c, 0xd3, 0x63, 0x8e, 0x37, 0x0f, 0x26, 0x54, + 0x6a, 0x39, 0x1e, 0x16, 0x38, 0x9c, 0x1e, 0x67, 0x73, 0xbb, 0xf7, 0x98, 0xc2, 0xca, 0xb8, 0x55, + 0x4e, 0x70, 0xc2, 0x29, 0xde, 0x46, 0x84, 0xb9, 0x89, 0xae, 0x11, 0xe6, 0xe6, 0xa1, 0x14, 0xb6, + 0x37, 0xeb, 0x7e, 0xd3, 0x71, 0x3d, 0x66, 0xd1, 0xd7, 0xae, 0x5e, 0x55, 0x89, 0xc0, 0x31, 0x0d, + 0x5a, 0x85, 0x21, 0x47, 0x5a, 0xae, 0x50, 0x7e, 0x4c, 0x21, 0x65, 0xaf, 0xe2, 0x61, 0x36, 0xa4, + 0xad, 0x4a, 0x95, 0x45, 0xaf, 0xc0, 0xa8, 0x78, 0x68, 0x2d, 0xb2, 0x9a, 0x4e, 0x99, 0xaf, 0xe1, + 0xaa, 0x3a, 0x12, 0x9b, 0xb4, 0xe8, 0x26, 0x0c, 0x47, 0x7e, 0x83, 0x3d, 0xe9, 0xa2, 0x62, 0xde, + 0x99, 0xfc, 0xe8, 0x78, 0x1b, 0x8a, 0x4c, 0x57, 0x1a, 0xab, 0xa2, 0x58, 0xe7, 0x83, 0x36, 0xf8, + 0x7c, 0x67, 0x81, 0xef, 0x49, 0x38, 0xfd, 0x50, 0xfe, 0x99, 0xa4, 0xe2, 0xe3, 0x9b, 0xcb, 0x41, + 0x94, 0xc4, 0x3a, 0x1b, 0x74, 0x05, 0x26, 0x5b, 0x81, 0xeb, 0xb3, 0x39, 0xa1, 0x8c, 0x96, 0xd3, + 0x66, 0x9a, 0xab, 0x4a, 0x92, 0x00, 0xa7, 0xcb, 0xb0, 0x77, 0xf2, 0x02, 0x38, 0x7d, 0x96, 0xa7, + 0xea, 0xe0, 0x37, 0x59, 0x0e, 0xc3, 0x0a, 0x8b, 0xd6, 0xd8, 0x4e, 0xcc, 0x95, 0x30, 0xd3, 0x33, + 0xf9, 0x61, 0x8c, 0x74, 0x65, 0x0d, 0x17, 0x5e, 0xd5, 0x5f, 0x1c, 0x73, 0x40, 0x75, 0x2d, 0x43, + 0x26, 0xbd, 0x02, 0x84, 0xd3, 0x8f, 0x74, 0xf0, 0x07, 0x4c, 0x5c, 0x8a, 0x62, 0x81, 0xc0, 0x00, + 0x87, 0x38, 0xc1, 0x13, 0x7d, 0x18, 0x26, 0x44, 0xf0, 0xc5, 0xb8, 0x9b, 0xce, 0xc5, 0x8e, 0xf2, + 0x38, 0x81, 0xc3, 0x29, 0x6a, 0x9e, 0x2a, 0xc3, 0xd9, 0x6c, 0x10, 0xb1, 0xf5, 0x5d, 0x77, 0xbd, + 0xdd, 0x70, 0xfa, 0x3c, 0xdb, 0x1f, 0x44, 0xaa, 0x8c, 0x24, 0x16, 0x67, 0x94, 0x40, 0x1b, 0x30, + 0xd1, 0x0a, 0x08, 0x69, 0x32, 0x41, 0x5f, 0x9c, 0x67, 0xb3, 0x3c, 0x4c, 0x04, 0x6d, 0x49, 0x25, + 0x81, 0x3b, 0xcc, 0x80, 0xe1, 0x14, 0x07, 0x74, 0x07, 0x86, 0xfc, 0x3d, 0x12, 0xec, 0x10, 0xa7, + 0x3e, 0x7d, 0xa1, 0xc3, 0xc3, 0x0d, 0x71, 0xb8, 0xdd, 0x10, 0xb4, 0x09, 0x47, 0x07, 0x09, 0xee, + 0xee, 0xe8, 0x20, 0x2b, 0x43, 0x7f, 0xde, 0x82, 0xb3, 0xd2, 0x36, 0x52, 0x6d, 0xd1, 0x5e, 0x5f, + 0xf2, 0xbd, 0x30, 0x0a, 0x78, 0x60, 0x83, 0x47, 0xf3, 0x1f, 0xfb, 0x6f, 0xe4, 0x14, 0x52, 0x7a, + 0xe0, 0xb3, 0x79, 0x14, 0x21, 0xce, 0xaf, 0x11, 0x2d, 0xc1, 0x64, 0x48, 0x22, 0xb9, 0x19, 0x2d, + 0x84, 0xab, 0xaf, 0x2f, 0xaf, 0x4f, 0x3f, 0xc6, 0xa3, 0x32, 0xd0, 0xc5, 0x50, 0x4d, 0x22, 0x71, + 0x9a, 0x1e, 0x5d, 0x86, 0x82, 0x1f, 0x4e, 0x3f, 0xde, 0x21, 0xa9, 0xaa, 0x5f, 0xbf, 0x51, 0xe5, + 0x0e, 0x6f, 0x37, 0xaa, 0xb8, 0xe0, 0x87, 0x32, 0x5d, 0x05, 0xbd, 0x8f, 0x85, 0xd3, 0x4f, 0x70, + 0xad, 0xa1, 0x4c, 0x57, 0xc1, 0x80, 0x38, 0xc6, 0xa3, 0x1d, 0x18, 0x0f, 0x8d, 0x7b, 0x6f, 0x38, + 0x7d, 0x91, 0xf5, 0xd4, 0x13, 0x79, 0x83, 0x66, 0x50, 0x6b, 0xd1, 0xe6, 0x4d, 0x2e, 0x38, 0xc9, + 0x96, 0xaf, 0x2e, 0xed, 0x82, 0x1f, 0x4e, 0x3f, 0xd9, 0x65, 0x75, 0x69, 0xc4, 0xfa, 0xea, 0xd2, + 0x79, 0xe0, 0x04, 0xcf, 0x99, 0xef, 0x84, 0xc9, 0x94, 0xb8, 0x74, 0x94, 0x4c, 0x4c, 0x33, 0xbb, + 0x30, 0x6a, 0x4c, 0xc9, 0x07, 0xea, 0x58, 0xf0, 0x2f, 0x06, 0xa1, 0xa4, 0x8c, 0xce, 0x68, 0xde, + 0xf4, 0x25, 0x38, 0x9b, 0xf4, 0x25, 0x18, 0xaa, 0xf8, 0x75, 0xc3, 0x7d, 0x60, 0x23, 0x23, 0x76, + 0x5f, 0xde, 0x06, 0xd8, 0xfb, 0x9b, 0x06, 0x4d, 0x93, 0x5f, 0xec, 0xd9, 0x29, 0xa1, 0xaf, 0xa3, + 0x71, 0xe0, 0x0a, 0x4c, 0x7a, 0x3e, 0x93, 0xd1, 0x49, 0x5d, 0x0a, 0x60, 0x4c, 0xce, 0x2a, 0xe9, + 0xc1, 0x70, 0x12, 0x04, 0x38, 0x5d, 0x86, 0x56, 0xc8, 0x05, 0xa5, 0xa4, 0x35, 0x82, 0xcb, 0x51, + 0x58, 0x60, 0xd1, 0x63, 0xd0, 0xdf, 0xf2, 0xeb, 0xe5, 0x8a, 0x90, 0xcf, 0xb5, 0x88, 0xb1, 0xf5, + 0x72, 0x05, 0x73, 0x1c, 0x5a, 0x80, 0x01, 0xf6, 0x23, 0x9c, 0x1e, 0xc9, 0x8f, 0x7a, 0xc2, 0x4a, + 0x68, 0x79, 0xae, 0x58, 0x01, 0x2c, 0x0a, 0x32, 0xad, 0x28, 0xbd, 0xd4, 0x30, 0xad, 0xe8, 0xe0, + 0x7d, 0x6a, 0x45, 0x25, 0x03, 0x1c, 0xf3, 0x42, 0x77, 0xe1, 0xb4, 0x71, 0x91, 0xe4, 0x53, 0x84, + 0x84, 0x22, 0xf2, 0xc2, 0x63, 0x1d, 0x6f, 0x90, 0xc2, 0x89, 0xe1, 0x9c, 0x68, 0xf4, 0xe9, 0x72, + 0x16, 0x27, 0x9c, 0x5d, 0x01, 0x6a, 0xc0, 0x64, 0x2d, 0x55, 0xeb, 0x50, 0xef, 0xb5, 0xaa, 0x01, + 0x4d, 0xd7, 0x98, 0x66, 0x8c, 0x5e, 0x81, 0xa1, 0x37, 0xfd, 0x90, 0x9d, 0x6d, 0xe2, 0x4e, 0x21, + 0x9f, 0xed, 0x0f, 0xbd, 0x7e, 0xa3, 0xca, 0xe0, 0x87, 0x07, 0xb3, 0xc3, 0x15, 0xbf, 0x2e, 0xff, + 0x62, 0x55, 0x00, 0x7d, 0xbf, 0x05, 0x33, 0xe9, 0x9b, 0xaa, 0x6a, 0xf4, 0x68, 0xef, 0x8d, 0xb6, + 0x45, 0xa5, 0x33, 0x2b, 0xb9, 0xec, 0x70, 0x87, 0xaa, 0xec, 0x5f, 0xb4, 0x98, 0x6e, 0x55, 0x18, + 0x07, 0x49, 0xd8, 0x6e, 0x9c, 0x44, 0x7a, 0xdf, 0x15, 0xc3, 0x6e, 0x79, 0xdf, 0x4e, 0x2d, 0xff, + 0xc4, 0x62, 0x4e, 0x2d, 0x27, 0xf8, 0x7a, 0xe5, 0x75, 0x18, 0x8a, 0x64, 0xda, 0xe5, 0x0e, 0x19, + 0x89, 0xb5, 0x46, 0x31, 0xc7, 0x1e, 0x25, 0xe1, 0xab, 0x0c, 0xcb, 0x8a, 0x8d, 0xfd, 0x0f, 0xf8, + 0x08, 0x48, 0xcc, 0x09, 0x98, 0x87, 0x96, 0x4d, 0xf3, 0xd0, 0x6c, 0x97, 0x2f, 0xc8, 0x31, 0x13, + 0xfd, 0x7d, 0xb3, 0xdd, 0x4c, 0xb3, 0xf5, 0x4e, 0xf7, 0xa6, 0xb2, 0x3f, 0x6f, 0x01, 0xc4, 0x01, + 0xb9, 0x7b, 0x48, 0xac, 0xf7, 0x12, 0x95, 0xe9, 0xfd, 0xc8, 0xaf, 0xf9, 0x0d, 0x61, 0xfc, 0x7c, + 0x24, 0xb6, 0x50, 0x71, 0xf8, 0xa1, 0xf6, 0x1b, 0x2b, 0x6a, 0x34, 0x2b, 0xc3, 0xff, 0x15, 0x63, + 0x9b, 0xa9, 0x11, 0xfa, 0xef, 0x8b, 0x16, 0x9c, 0xca, 0x72, 0x85, 0xa6, 0x37, 0x44, 0xae, 0xe3, + 0x53, 0x9e, 0x6e, 0x6a, 0x34, 0x6f, 0x09, 0x38, 0x56, 0x14, 0x3d, 0x67, 0x2c, 0x3c, 0x5a, 0x24, + 0xec, 0x1b, 0x30, 0x5a, 0x09, 0x88, 0x76, 0xb8, 0xbe, 0xca, 0x43, 0x4a, 0xf0, 0xf6, 0x3c, 0x73, + 0xe4, 0x70, 0x12, 0xf6, 0x97, 0x0b, 0x70, 0x8a, 0x3b, 0x8c, 0x2c, 0xec, 0xf9, 0x6e, 0xbd, 0xe2, + 0xd7, 0xc5, 0x83, 0xb7, 0x8f, 0xc1, 0x48, 0x4b, 0x53, 0xcc, 0x76, 0x8a, 0xea, 0xaa, 0x2b, 0x70, + 0x63, 0x55, 0x92, 0x0e, 0xc5, 0x06, 0x2f, 0x54, 0x87, 0x11, 0xb2, 0xe7, 0xd6, 0x94, 0xd7, 0x41, + 0xe1, 0xc8, 0x07, 0x9d, 0xaa, 0x65, 0x45, 0xe3, 0x83, 0x0d, 0xae, 0x0f, 0x20, 0x8f, 0xb8, 0xfd, + 0xa3, 0x16, 0x3c, 0x94, 0x13, 0x03, 0x96, 0x56, 0x77, 0x87, 0xb9, 0xe6, 0x88, 0x69, 0xab, 0xaa, + 0xe3, 0x0e, 0x3b, 0x58, 0x60, 0xd1, 0x47, 0x00, 0xb8, 0xc3, 0x0d, 0xf1, 0x6a, 0x5d, 0x83, 0x65, + 0x1a, 0x71, 0xfe, 0xb4, 0x90, 0x6d, 0xb2, 0x3c, 0xd6, 0x78, 0xd9, 0x5f, 0xec, 0x83, 0x7e, 0xe6, + 0xe0, 0x81, 0x2a, 0x30, 0xb8, 0xc3, 0xb3, 0xfa, 0x74, 0x1c, 0x37, 0x4a, 0x2b, 0x13, 0x05, 0xc5, + 0xe3, 0xa6, 0x41, 0xb1, 0x64, 0x83, 0xd6, 0x60, 0x8a, 0x27, 0x57, 0x6a, 0x2c, 0x93, 0x86, 0xb3, + 0x2f, 0x75, 0x9e, 0x3c, 0x13, 0xb0, 0xd2, 0xfd, 0x96, 0xd3, 0x24, 0x38, 0xab, 0x1c, 0x7a, 0x15, + 0xc6, 0xe8, 0x1d, 0xd4, 0x6f, 0x47, 0x92, 0x13, 0x4f, 0xab, 0xa4, 0xc4, 0xf2, 0x0d, 0x03, 0x8b, + 0x13, 0xd4, 0xe8, 0x15, 0x18, 0x6d, 0xa5, 0xb4, 0xbb, 0xfd, 0xb1, 0x1a, 0xc4, 0xd4, 0xe8, 0x9a, + 0xb4, 0xcc, 0x1b, 0xba, 0xcd, 0x7c, 0xbf, 0x37, 0x76, 0x02, 0x12, 0xee, 0xf8, 0x8d, 0x3a, 0x13, + 0xff, 0xfa, 0x35, 0x6f, 0xe8, 0x04, 0x1e, 0xa7, 0x4a, 0x50, 0x2e, 0x5b, 0x8e, 0xdb, 0x68, 0x07, + 0x24, 0xe6, 0x32, 0x60, 0x72, 0x59, 0x4d, 0xe0, 0x71, 0xaa, 0x44, 0x77, 0xb5, 0xf5, 0xe0, 0xf1, + 0xa8, 0xad, 0xed, 0x9f, 0x2a, 0x80, 0x31, 0xb4, 0xdf, 0xbe, 0xe9, 0x9e, 0xe8, 0x97, 0x6d, 0x07, + 0xad, 0x9a, 0x70, 0x66, 0xca, 0xfc, 0xb2, 0x38, 0x8b, 0x2b, 0xff, 0x32, 0xfa, 0x1f, 0xb3, 0x52, + 0x74, 0x8d, 0x9f, 0xae, 0x04, 0x3e, 0x3d, 0xe4, 0x64, 0xd0, 0x31, 0xf5, 0xe8, 0x60, 0x50, 0x3e, + 0xc8, 0xee, 0x10, 0x9e, 0x53, 0xb8, 0x65, 0x73, 0x0e, 0x86, 0xdf, 0x4f, 0x55, 0x44, 0x46, 0x90, + 0x5c, 0xd0, 0x65, 0x18, 0x16, 0x39, 0x7c, 0x98, 0x6f, 0x3c, 0x5f, 0x4c, 0xcc, 0x4f, 0x69, 0x39, + 0x06, 0x63, 0x9d, 0xc6, 0xfe, 0x81, 0x02, 0x4c, 0x65, 0x3c, 0x6e, 0xe2, 0xc7, 0xc8, 0xb6, 0x1b, + 0x46, 0x2a, 0x51, 0xac, 0x76, 0x8c, 0x70, 0x38, 0x56, 0x14, 0x74, 0xaf, 0xe2, 0x07, 0x55, 0xf2, + 0x70, 0x12, 0x8f, 0x07, 0x04, 0xf6, 0x88, 0x29, 0x57, 0x2f, 0x40, 0x5f, 0x3b, 0x24, 0x32, 0xb0, + 0xae, 0x3a, 0xb6, 0x99, 0x4d, 0x97, 0x61, 0xe8, 0x35, 0x6a, 0x5b, 0x99, 0x47, 0xb5, 0x6b, 0x14, + 0x37, 0x90, 0x72, 0x1c, 0x6d, 0x5c, 0x44, 0x3c, 0xc7, 0x8b, 0xc4, 0x65, 0x2b, 0x8e, 0x10, 0xc9, + 0xa0, 0x58, 0x60, 0xed, 0x2f, 0x14, 0xe1, 0x6c, 0xee, 0x73, 0x47, 0xda, 0xf4, 0xa6, 0xef, 0xb9, + 0x91, 0xaf, 0x1c, 0xc0, 0x78, 0x54, 0x48, 0xd2, 0xda, 0x59, 0x13, 0x70, 0xac, 0x28, 0xd0, 0x45, + 0xe8, 0x67, 0x1a, 0xe1, 0x54, 0xca, 0xdc, 0xc5, 0x65, 0x1e, 0x26, 0x8c, 0xa3, 0x7b, 0xce, 0x72, + 0xfe, 0x18, 0x95, 0x60, 0xfc, 0x46, 0xf2, 0x40, 0xa1, 0xcd, 0xf5, 0xfd, 0x06, 0x66, 0x48, 0xf4, + 0x84, 0xe8, 0xaf, 0x84, 0xc7, 0x13, 0x76, 0xea, 0x7e, 0xa8, 0x75, 0xda, 0x53, 0x30, 0xb8, 0x4b, + 0xf6, 0x03, 0xd7, 0xdb, 0x4e, 0x7a, 0xc2, 0x5d, 0xe3, 0x60, 0x2c, 0xf1, 0x66, 0x8e, 0xc7, 0xc1, + 0xe3, 0x4e, 0x4f, 0x3e, 0xd4, 0x55, 0x3c, 0xf9, 0xa1, 0x22, 0x8c, 0xe3, 0xc5, 0xe5, 0x77, 0x07, + 0xe2, 0x66, 0x7a, 0x20, 0x8e, 0x3b, 0x3d, 0x79, 0xf7, 0xd1, 0xf8, 0x39, 0x0b, 0xc6, 0x59, 0x26, + 0x21, 0x11, 0xd4, 0xc0, 0xf5, 0xbd, 0x13, 0xb8, 0x0a, 0x3c, 0x06, 0xfd, 0x01, 0xad, 0x34, 0x99, + 0x2b, 0x97, 0xb5, 0x04, 0x73, 0x1c, 0x7a, 0x04, 0xfa, 0x58, 0x13, 0xe8, 0xe0, 0x8d, 0xf0, 0x2d, + 0x78, 0xd9, 0x89, 0x1c, 0xcc, 0xa0, 0x2c, 0x48, 0x16, 0x26, 0xad, 0x86, 0xcb, 0x1b, 0x1d, 0xdb, + 0xeb, 0xdf, 0x19, 0x81, 0x10, 0x32, 0x9b, 0xf6, 0xf6, 0x82, 0x64, 0x65, 0xb3, 0xec, 0x7c, 0xcd, + 0xfe, 0xc3, 0x02, 0x9c, 0xcf, 0x2c, 0xd7, 0x73, 0x90, 0xac, 0xce, 0xa5, 0x1f, 0x64, 0xae, 0x98, + 0xe2, 0x09, 0xfa, 0x19, 0xf7, 0xf5, 0x2a, 0xfd, 0xf7, 0xf7, 0x10, 0xbb, 0x2a, 0xb3, 0xcb, 0xde, + 0x21, 0xb1, 0xab, 0x32, 0xdb, 0x96, 0xa3, 0x26, 0xf8, 0xd3, 0x42, 0xce, 0xb7, 0x30, 0x85, 0xc1, + 0x25, 0xba, 0xcf, 0x30, 0x64, 0x28, 0x2f, 0xe1, 0x7c, 0x8f, 0xe1, 0x30, 0xac, 0xb0, 0x68, 0x01, + 0xc6, 0x9b, 0xae, 0x47, 0x37, 0x9f, 0x7d, 0x53, 0x14, 0x57, 0x8a, 0xfc, 0x35, 0x13, 0x8d, 0x93, + 0xf4, 0xc8, 0xd5, 0xe2, 0x5a, 0xf1, 0xaf, 0x7b, 0xe5, 0x48, 0xab, 0x6e, 0xce, 0xf4, 0x65, 0x50, + 0xbd, 0x98, 0x11, 0xe3, 0x6a, 0x4d, 0xd3, 0x13, 0x15, 0x7b, 0xd7, 0x13, 0x8d, 0x64, 0xeb, 0x88, + 0x66, 0x5e, 0x81, 0xd1, 0xfb, 0x36, 0x0c, 0xd8, 0x5f, 0x2f, 0xc2, 0xc3, 0x1d, 0x96, 0x3d, 0xdf, + 0xeb, 0x8d, 0x31, 0xd0, 0xf6, 0xfa, 0xd4, 0x38, 0x54, 0xe0, 0xd4, 0x56, 0xbb, 0xd1, 0xd8, 0x67, + 0xcf, 0x6f, 0x48, 0x5d, 0x52, 0x08, 0x99, 0x52, 0x2a, 0x47, 0x4e, 0xad, 0x66, 0xd0, 0xe0, 0xcc, + 0x92, 0xf4, 0x8a, 0x45, 0x4f, 0x92, 0x7d, 0xc5, 0x2a, 0x71, 0xc5, 0xc2, 0x3a, 0x12, 0x9b, 0xb4, + 0xe8, 0x0a, 0x4c, 0x3a, 0x7b, 0x8e, 0xcb, 0x83, 0x83, 0x4b, 0x06, 0xfc, 0x8e, 0xa5, 0xf4, 0xb9, + 0x0b, 0x49, 0x02, 0x9c, 0x2e, 0x83, 0x5e, 0x03, 0xe4, 0x6f, 0x32, 0x27, 0xfd, 0xfa, 0x15, 0xe2, + 0x09, 0x93, 0x33, 0x1b, 0xbb, 0x62, 0xbc, 0x25, 0xdc, 0x48, 0x51, 0xe0, 0x8c, 0x52, 0x89, 0x20, + 0x4e, 0x03, 0xf9, 0x41, 0x9c, 0x3a, 0xef, 0x8b, 0x5d, 0xd3, 0x14, 0x5d, 0x86, 0xd1, 0x23, 0xba, + 0x9e, 0xda, 0xff, 0xc1, 0xa2, 0x27, 0x1e, 0x2f, 0x63, 0x46, 0x48, 0x7d, 0x85, 0xf9, 0xc6, 0x72, + 0xf5, 0xb0, 0x16, 0x25, 0xe7, 0xb4, 0xe6, 0x1b, 0x1b, 0x23, 0xb1, 0x49, 0xcb, 0xe7, 0x90, 0xe6, + 0xd3, 0x6a, 0xdc, 0x0a, 0x44, 0x18, 0x37, 0x45, 0x81, 0x3e, 0x0a, 0x83, 0x75, 0x77, 0xcf, 0x0d, + 0x85, 0x72, 0xec, 0xc8, 0x96, 0xa8, 0x78, 0xeb, 0x5c, 0xe6, 0x6c, 0xb0, 0xe4, 0x67, 0xff, 0x50, + 0x21, 0xee, 0x93, 0xd7, 0xdb, 0x7e, 0xe4, 0x9c, 0xc0, 0x49, 0x7e, 0xc5, 0x38, 0xc9, 0x9f, 0xe8, + 0x14, 0xcb, 0x8e, 0x35, 0x29, 0xf7, 0x04, 0xbf, 0x91, 0x38, 0xc1, 0x9f, 0xec, 0xce, 0xaa, 0xf3, + 0xc9, 0xfd, 0x0f, 0x2d, 0x98, 0x34, 0xe8, 0x4f, 0xe0, 0x00, 0x59, 0x35, 0x0f, 0x90, 0x47, 0xbb, + 0x7e, 0x43, 0xce, 0xc1, 0xf1, 0xbd, 0xc5, 0x44, 0xdb, 0xd9, 0x81, 0xf1, 0x26, 0xf4, 0xed, 0x38, + 0x41, 0xbd, 0x53, 0xee, 0x8e, 0x54, 0xa1, 0xb9, 0xab, 0x4e, 0x20, 0xcc, 0xf4, 0xcf, 0xc8, 0x5e, + 0xa7, 0xa0, 0xae, 0x26, 0x7a, 0x56, 0x15, 0x7a, 0x09, 0x06, 0xc2, 0x9a, 0xdf, 0x52, 0xef, 0x75, + 0x2e, 0xb0, 0x8e, 0x66, 0x90, 0xc3, 0x83, 0x59, 0x64, 0x56, 0x47, 0xc1, 0x58, 0xd0, 0xa3, 0x8f, + 0xc1, 0x28, 0xfb, 0xa5, 0x7c, 0xe6, 0x8a, 0xf9, 0x1a, 0x8c, 0xaa, 0x4e, 0xc8, 0x1d, 0x4a, 0x0d, + 0x10, 0x36, 0x59, 0xcd, 0x6c, 0x43, 0x49, 0x7d, 0xd6, 0x03, 0x35, 0xf5, 0xfe, 0xbb, 0x22, 0x4c, + 0x65, 0xcc, 0x39, 0x14, 0x1a, 0x23, 0x71, 0xb9, 0xc7, 0xa9, 0xfa, 0x36, 0xc7, 0x22, 0x64, 0x17, + 0xa8, 0xba, 0x98, 0x5b, 0x3d, 0x57, 0x7a, 0x33, 0x24, 0xc9, 0x4a, 0x29, 0xa8, 0x7b, 0xa5, 0xb4, + 0xb2, 0x13, 0xeb, 0x6a, 0x5a, 0x91, 0x6a, 0xe9, 0x03, 0x1d, 0xd3, 0x5f, 0xee, 0x83, 0x53, 0x59, + 0xe1, 0x35, 0xd1, 0x67, 0x12, 0x99, 0x63, 0x5f, 0xe8, 0x35, 0x30, 0x27, 0x4f, 0x27, 0x2b, 0xc2, + 0xfe, 0xcd, 0x99, 0xb9, 0x64, 0xbb, 0x76, 0xb3, 0xa8, 0x93, 0x05, 0x1e, 0x09, 0x78, 0xc6, 0x5f, + 0xb9, 0x7d, 0xbc, 0xbf, 0xe7, 0x06, 0x88, 0x54, 0xc1, 0x61, 0xc2, 0x1f, 0x47, 0x82, 0xbb, 0xfb, + 0xe3, 0xc8, 0x9a, 0x51, 0x19, 0x06, 0x6a, 0xdc, 0xd1, 0xa3, 0xd8, 0x7d, 0x0b, 0xe3, 0x5e, 0x1e, + 0x6a, 0x03, 0x16, 0xde, 0x1d, 0x82, 0xc1, 0x8c, 0x0b, 0xc3, 0x5a, 0xc7, 0x3c, 0xd0, 0xc9, 0xb3, + 0x4b, 0x0f, 0x3e, 0xad, 0x0b, 0x1e, 0xe8, 0x04, 0xfa, 0x51, 0x0b, 0x12, 0xaf, 0x3d, 0x94, 0x52, + 0xce, 0xca, 0x55, 0xca, 0x5d, 0x80, 0xbe, 0xc0, 0x6f, 0x90, 0x64, 0xb6, 0x56, 0xec, 0x37, 0x08, + 0x66, 0x18, 0x4a, 0x11, 0xc5, 0xaa, 0x96, 0x11, 0xfd, 0x1a, 0x29, 0x2e, 0x88, 0x8f, 0x41, 0x7f, + 0x83, 0xec, 0x91, 0x46, 0x32, 0xa9, 0xd6, 0x75, 0x0a, 0xc4, 0x1c, 0x67, 0xff, 0x5c, 0x1f, 0x9c, + 0xeb, 0x18, 0x05, 0x88, 0x5e, 0xc6, 0xb6, 0x9d, 0x88, 0xdc, 0x71, 0xf6, 0x93, 0xd9, 0x6f, 0xae, + 0x70, 0x30, 0x96, 0x78, 0xf6, 0xf4, 0x90, 0x07, 0xb1, 0x4f, 0xa8, 0x30, 0x45, 0xec, 0x7a, 0x81, + 0x35, 0x55, 0x62, 0xc5, 0xe3, 0x50, 0x89, 0x3d, 0x07, 0x10, 0x86, 0x0d, 0xee, 0x13, 0x57, 0x17, + 0x6f, 0x1a, 0xe3, 0x64, 0x07, 0xd5, 0xeb, 0x02, 0x83, 0x35, 0x2a, 0xb4, 0x0c, 0x13, 0xad, 0xc0, + 0x8f, 0xb8, 0x46, 0x78, 0x99, 0xbb, 0x8d, 0xf6, 0x9b, 0x01, 0x58, 0x2a, 0x09, 0x3c, 0x4e, 0x95, + 0x40, 0x2f, 0xc2, 0xb0, 0x08, 0xca, 0x52, 0xf1, 0xfd, 0x86, 0x50, 0x42, 0x29, 0x4f, 0xca, 0x6a, + 0x8c, 0xc2, 0x3a, 0x9d, 0x56, 0x8c, 0xa9, 0x99, 0x07, 0x33, 0x8b, 0x71, 0x55, 0xb3, 0x46, 0x97, + 0x88, 0xda, 0x3b, 0xd4, 0x53, 0xd4, 0xde, 0x58, 0x2d, 0x57, 0xea, 0xd9, 0xea, 0x09, 0x5d, 0x15, + 0x59, 0x5f, 0xe9, 0x83, 0x29, 0x31, 0x71, 0x1e, 0xf4, 0x74, 0xb9, 0x99, 0x9e, 0x2e, 0xc7, 0xa1, + 0xb8, 0x7b, 0x77, 0xce, 0x9c, 0xf4, 0x9c, 0xf9, 0x61, 0x0b, 0x4c, 0x49, 0x0d, 0xfd, 0x99, 0xdc, + 0xf4, 0x61, 0x2f, 0xe6, 0x4a, 0x7e, 0xca, 0x6b, 0xf0, 0x6d, 0x26, 0x12, 0xb3, 0xff, 0xbd, 0x05, + 0x8f, 0x76, 0xe5, 0x88, 0x56, 0xa0, 0xc4, 0xc4, 0x49, 0xed, 0xa2, 0xf7, 0xa4, 0x72, 0x2b, 0x97, + 0x88, 0x1c, 0xe9, 0x36, 0x2e, 0x89, 0x56, 0x52, 0x79, 0xda, 0x9e, 0xca, 0xc8, 0xd3, 0x76, 0xda, + 0xe8, 0x9e, 0xfb, 0x4c, 0xd4, 0xf6, 0x83, 0xf4, 0xc4, 0x31, 0x9e, 0x74, 0xa1, 0xf7, 0x1b, 0x4a, + 0x47, 0x3b, 0xa1, 0x74, 0x44, 0x26, 0xb5, 0x76, 0x86, 0x7c, 0x18, 0x26, 0x58, 0xb4, 0x36, 0xf6, + 0xc8, 0x41, 0x3c, 0x36, 0x2b, 0xc4, 0x8e, 0xcc, 0xd7, 0x13, 0x38, 0x9c, 0xa2, 0xb6, 0xff, 0xa0, + 0x08, 0x03, 0x7c, 0xf9, 0x9d, 0xc0, 0xf5, 0xf2, 0x69, 0x28, 0xb9, 0xcd, 0x66, 0x9b, 0xa7, 0xde, + 0xea, 0x8f, 0xdd, 0x62, 0xcb, 0x12, 0x88, 0x63, 0x3c, 0x5a, 0x15, 0xfa, 0xee, 0x0e, 0x01, 0x61, + 0x79, 0xc3, 0xe7, 0x96, 0x9d, 0xc8, 0xe1, 0xb2, 0x92, 0x3a, 0x67, 0x63, 0xcd, 0x38, 0xfa, 0x24, + 0x40, 0x18, 0x05, 0xae, 0xb7, 0x4d, 0x61, 0x22, 0x0e, 0xf5, 0x7b, 0x3b, 0x70, 0xab, 0x2a, 0x62, + 0xce, 0x33, 0xde, 0x73, 0x14, 0x02, 0x6b, 0x1c, 0xd1, 0x9c, 0x71, 0xd2, 0xcf, 0x24, 0xc6, 0x0e, + 0x38, 0xd7, 0x78, 0xcc, 0x66, 0x3e, 0x00, 0x25, 0xc5, 0xbc, 0x9b, 0xf6, 0x6b, 0x44, 0x17, 0x8b, + 0x3e, 0x04, 0xe3, 0x89, 0xb6, 0x1d, 0x49, 0x79, 0xf6, 0xf3, 0x16, 0x8c, 0xf3, 0xc6, 0xac, 0x78, + 0x7b, 0xe2, 0x34, 0x78, 0x0b, 0x4e, 0x35, 0x32, 0x76, 0x65, 0x31, 0xfc, 0xbd, 0xef, 0xe2, 0x4a, + 0x59, 0x96, 0x85, 0xc5, 0x99, 0x75, 0xa0, 0x4b, 0x74, 0xc5, 0xd1, 0x5d, 0xd7, 0x69, 0x88, 0xb7, + 0xf5, 0x23, 0x7c, 0xb5, 0x71, 0x18, 0x56, 0x58, 0xfb, 0xb7, 0x2d, 0x98, 0xe4, 0x2d, 0xbf, 0x46, + 0xf6, 0xd5, 0xde, 0xf4, 0xcd, 0x6c, 0xbb, 0x48, 0xfa, 0x58, 0xc8, 0x49, 0xfa, 0xa8, 0x7f, 0x5a, + 0xb1, 0xe3, 0xa7, 0x7d, 0xd9, 0x02, 0x31, 0x43, 0x4e, 0x40, 0x9f, 0xf1, 0x9d, 0xa6, 0x3e, 0x63, + 0x26, 0x7f, 0x11, 0xe4, 0x28, 0x32, 0xfe, 0xc4, 0x82, 0x09, 0x4e, 0x10, 0xdb, 0xea, 0xbf, 0xa9, + 0xe3, 0xd0, 0x4b, 0x6a, 0xf8, 0x6b, 0x64, 0x7f, 0xc3, 0xaf, 0x38, 0xd1, 0x4e, 0xf6, 0x47, 0x19, + 0x83, 0xd5, 0xd7, 0x71, 0xb0, 0xea, 0x72, 0x01, 0x19, 0x39, 0x91, 0xba, 0xbc, 0x90, 0x3f, 0x6a, + 0x4e, 0x24, 0xfb, 0x1b, 0x16, 0x20, 0x5e, 0x8d, 0x21, 0xb8, 0x51, 0x71, 0x88, 0x41, 0xb5, 0x83, + 0x2e, 0xde, 0x9a, 0x14, 0x06, 0x6b, 0x54, 0xc7, 0xd2, 0x3d, 0x09, 0x87, 0x8b, 0x62, 0x77, 0x87, + 0x8b, 0x23, 0xf4, 0xe8, 0xbf, 0x1c, 0x80, 0xe4, 0xb3, 0x36, 0x74, 0x0b, 0x46, 0x6a, 0x4e, 0xcb, + 0xd9, 0x74, 0x1b, 0x6e, 0xe4, 0x92, 0xb0, 0x93, 0x37, 0xd6, 0x92, 0x46, 0x27, 0x4c, 0xe4, 0x1a, + 0x04, 0x1b, 0x7c, 0xd0, 0x1c, 0x40, 0x2b, 0x70, 0xf7, 0xdc, 0x06, 0xd9, 0x66, 0x6a, 0x17, 0x16, + 0xcd, 0x83, 0xbb, 0x86, 0x49, 0x28, 0xd6, 0x28, 0x32, 0x62, 0x08, 0x14, 0x1f, 0x70, 0x0c, 0x01, + 0x38, 0xb1, 0x18, 0x02, 0x7d, 0x47, 0x8a, 0x21, 0x30, 0x74, 0xe4, 0x18, 0x02, 0xfd, 0x3d, 0xc5, + 0x10, 0xc0, 0x70, 0x46, 0xca, 0x9e, 0xf4, 0xff, 0xaa, 0xdb, 0x20, 0xe2, 0xc2, 0xc1, 0x43, 0x90, + 0xcc, 0xdc, 0x3b, 0x98, 0x3d, 0x83, 0x33, 0x29, 0x70, 0x4e, 0x49, 0xf4, 0x11, 0x98, 0x76, 0x1a, + 0x0d, 0xff, 0x8e, 0x1a, 0xd4, 0x95, 0xb0, 0xe6, 0x34, 0xb8, 0x09, 0x64, 0x90, 0x71, 0x7d, 0xe4, + 0xde, 0xc1, 0xec, 0xf4, 0x42, 0x0e, 0x0d, 0xce, 0x2d, 0x8d, 0x3e, 0x08, 0xa5, 0x56, 0xe0, 0xd7, + 0xd6, 0xb4, 0xb7, 0xb7, 0xe7, 0x69, 0x07, 0x56, 0x24, 0xf0, 0xf0, 0x60, 0x76, 0x54, 0xfd, 0x61, + 0x07, 0x7e, 0x5c, 0x20, 0x23, 0x28, 0xc0, 0xf0, 0xb1, 0x06, 0x05, 0xd8, 0x85, 0xa9, 0x2a, 0x09, + 0x5c, 0xa7, 0xe1, 0xbe, 0x45, 0xe5, 0x65, 0xb9, 0x3f, 0x6d, 0x40, 0x29, 0x48, 0xec, 0xc8, 0x3d, + 0x05, 0x69, 0xd5, 0x92, 0xd3, 0xc8, 0x1d, 0x38, 0x66, 0x64, 0xff, 0x6f, 0x0b, 0x06, 0xc5, 0x33, + 0xb6, 0x13, 0x90, 0x1a, 0x17, 0x0c, 0xa3, 0xc4, 0x6c, 0x76, 0x87, 0xb1, 0xc6, 0xe4, 0x9a, 0x23, + 0xca, 0x09, 0x73, 0xc4, 0xa3, 0x9d, 0x98, 0x74, 0x36, 0x44, 0xfc, 0xd5, 0x22, 0x95, 0xde, 0x8d, + 0x07, 0xd5, 0x0f, 0xbe, 0x0b, 0xd6, 0x61, 0x30, 0x14, 0x0f, 0x7a, 0x0b, 0xf9, 0x2f, 0x2a, 0x92, + 0x83, 0x18, 0x7b, 0xd1, 0x89, 0x27, 0xbc, 0x92, 0x49, 0xe6, 0x4b, 0xe1, 0xe2, 0x03, 0x7c, 0x29, + 0xdc, 0xed, 0xc9, 0x79, 0xdf, 0x71, 0x3c, 0x39, 0xb7, 0xbf, 0xc6, 0x4e, 0x4e, 0x1d, 0x7e, 0x02, + 0x42, 0xd5, 0x15, 0xf3, 0x8c, 0xb5, 0x3b, 0xcc, 0x2c, 0xd1, 0xa8, 0x1c, 0xe1, 0xea, 0x67, 0x2d, + 0x38, 0x97, 0xf1, 0x55, 0x9a, 0xa4, 0xf5, 0x0c, 0x0c, 0x39, 0xed, 0xba, 0xab, 0xd6, 0xb2, 0x66, + 0x9a, 0x5c, 0x10, 0x70, 0xac, 0x28, 0xd0, 0x12, 0x4c, 0x92, 0xbb, 0x2d, 0x97, 0x1b, 0x72, 0x75, + 0xe7, 0xe3, 0x22, 0x7f, 0xfb, 0xb8, 0x92, 0x44, 0xe2, 0x34, 0xbd, 0x0a, 0x4e, 0x54, 0xcc, 0x0d, + 0x4e, 0xf4, 0xb7, 0x2d, 0x18, 0x56, 0x4f, 0x5a, 0x1f, 0x78, 0x6f, 0x7f, 0xd8, 0xec, 0xed, 0x87, + 0x3b, 0xf4, 0x76, 0x4e, 0x37, 0xff, 0x66, 0x41, 0xb5, 0xb7, 0xe2, 0x07, 0x51, 0x0f, 0x12, 0xdc, + 0xfd, 0x3f, 0x9c, 0xb8, 0x0c, 0xc3, 0x4e, 0xab, 0x25, 0x11, 0xd2, 0x03, 0x8e, 0x85, 0xdc, 0x8e, + 0xc1, 0x58, 0xa7, 0x51, 0xef, 0x38, 0x8a, 0xb9, 0xef, 0x38, 0xea, 0x00, 0x91, 0x13, 0x6c, 0x93, + 0x88, 0xc2, 0x84, 0xc3, 0x6e, 0xfe, 0x7e, 0xd3, 0x8e, 0xdc, 0xc6, 0x9c, 0xeb, 0x45, 0x61, 0x14, + 0xcc, 0x95, 0xbd, 0xe8, 0x46, 0xc0, 0xaf, 0x90, 0x5a, 0x78, 0x2f, 0xc5, 0x0b, 0x6b, 0x7c, 0x65, + 0xf8, 0x06, 0x56, 0x47, 0xbf, 0xe9, 0x4a, 0xb1, 0x2e, 0xe0, 0x58, 0x51, 0xd8, 0x1f, 0x60, 0xa7, + 0x0f, 0xeb, 0xd3, 0xa3, 0x85, 0xb6, 0xfa, 0xf2, 0x88, 0x1a, 0x0d, 0x66, 0x14, 0x5d, 0xd6, 0x03, + 0x68, 0x75, 0xde, 0xec, 0x69, 0xc5, 0xfa, 0xab, 0xc2, 0x38, 0xca, 0x16, 0xfa, 0x78, 0xca, 0x3d, + 0xe6, 0xd9, 0x2e, 0xa7, 0xc6, 0x11, 0x1c, 0x62, 0x58, 0xfe, 0x1d, 0x96, 0x9d, 0xa4, 0x5c, 0x11, + 0xeb, 0x42, 0xcb, 0xbf, 0x23, 0x10, 0x38, 0xa6, 0xa1, 0xc2, 0x94, 0xfa, 0x13, 0x4e, 0xa3, 0x38, + 0x0e, 0xad, 0xa2, 0x0e, 0xb1, 0x46, 0x81, 0xe6, 0x85, 0x42, 0x81, 0xdb, 0x05, 0x1e, 0x4e, 0x28, + 0x14, 0x64, 0x77, 0x69, 0x5a, 0xa0, 0xcb, 0x30, 0xac, 0xb2, 0xad, 0x57, 0x78, 0xe6, 0x2b, 0x31, + 0xcd, 0x56, 0x62, 0x30, 0xd6, 0x69, 0xd0, 0x06, 0x8c, 0x87, 0x5c, 0xcf, 0xa6, 0x82, 0x83, 0x73, + 0x7d, 0xe5, 0x7b, 0xd5, 0x63, 0x62, 0x13, 0x7d, 0xc8, 0x40, 0x7c, 0x77, 0x92, 0x21, 0x16, 0x92, + 0x2c, 0xd0, 0xab, 0x30, 0xd6, 0xf0, 0x9d, 0xfa, 0xa2, 0xd3, 0x70, 0xbc, 0x1a, 0xeb, 0x9f, 0x21, + 0x33, 0x69, 0xef, 0x75, 0x03, 0x8b, 0x13, 0xd4, 0x54, 0x78, 0xd3, 0x21, 0x22, 0x44, 0x98, 0xe3, + 0x6d, 0x93, 0x50, 0xe4, 0xce, 0x66, 0xc2, 0xdb, 0xf5, 0x1c, 0x1a, 0x9c, 0x5b, 0x1a, 0xbd, 0x04, + 0x23, 0xf2, 0xf3, 0xb5, 0x88, 0x24, 0xf1, 0x93, 0x18, 0x0d, 0x87, 0x0d, 0x4a, 0x74, 0x07, 0x4e, + 0xcb, 0xff, 0x1b, 0x81, 0xb3, 0xb5, 0xe5, 0xd6, 0xc4, 0x33, 0x7d, 0xfe, 0x76, 0x76, 0x41, 0x3e, + 0xf0, 0x5c, 0xc9, 0x22, 0x3a, 0x3c, 0x98, 0xbd, 0x20, 0x7a, 0x2d, 0x13, 0xcf, 0x06, 0x31, 0x9b, + 0x3f, 0x5a, 0x83, 0xa9, 0x1d, 0xe2, 0x34, 0xa2, 0x9d, 0xa5, 0x1d, 0x52, 0xdb, 0x95, 0x8b, 0x8e, + 0xc5, 0x39, 0xd1, 0x9e, 0x8f, 0x5c, 0x4d, 0x93, 0xe0, 0xac, 0x72, 0xe8, 0x0d, 0x98, 0x6e, 0xb5, + 0x37, 0x1b, 0x6e, 0xb8, 0xb3, 0xee, 0x47, 0xcc, 0x11, 0x49, 0x25, 0x6f, 0x17, 0x01, 0x51, 0x54, + 0x24, 0x99, 0x4a, 0x0e, 0x1d, 0xce, 0xe5, 0x80, 0xde, 0x82, 0xd3, 0x89, 0xc9, 0x20, 0x42, 0x42, + 0x8c, 0xe5, 0xa7, 0x07, 0xa9, 0x66, 0x15, 0x10, 0xd1, 0x55, 0xb2, 0x50, 0x38, 0xbb, 0x0a, 0xf4, + 0x32, 0x80, 0xdb, 0x5a, 0x75, 0x9a, 0x6e, 0x83, 0x5e, 0x17, 0xa7, 0xd8, 0x3c, 0xa1, 0x57, 0x07, + 0x28, 0x57, 0x24, 0x94, 0xee, 0xcf, 0xe2, 0xdf, 0x3e, 0xd6, 0xa8, 0xd1, 0x75, 0x18, 0x13, 0xff, + 0xf6, 0xc5, 0xb0, 0xf2, 0xc8, 0x24, 0x8f, 0xb3, 0xb0, 0x52, 0x15, 0x1d, 0x73, 0x98, 0x82, 0xe0, + 0x44, 0x59, 0xb4, 0x0d, 0xe7, 0x64, 0xaa, 0x37, 0x7d, 0x8e, 0xca, 0x31, 0x08, 0x59, 0x4e, 0x8e, + 0x21, 0xfe, 0x32, 0x65, 0xa1, 0x13, 0x21, 0xee, 0xcc, 0x87, 0x9e, 0xed, 0xfa, 0x54, 0xe7, 0x6f, + 0x77, 0x4f, 0x73, 0x2f, 0x27, 0x7a, 0xb6, 0x5f, 0x4f, 0x22, 0x71, 0x9a, 0x1e, 0x85, 0x70, 0xda, + 0xf5, 0xb2, 0x66, 0xf6, 0x19, 0xc6, 0xe8, 0x43, 0xfc, 0xd9, 0x72, 0xe7, 0x59, 0x9d, 0x89, 0xe7, + 0xb3, 0x3a, 0x93, 0xf7, 0xdb, 0xf3, 0xff, 0xfb, 0x2d, 0x8b, 0x96, 0xd6, 0xa4, 0x74, 0xf4, 0x29, + 0x18, 0xd1, 0x3f, 0x4c, 0x48, 0x1c, 0x17, 0xb3, 0x85, 0x58, 0x6d, 0x6f, 0xe0, 0x32, 0xbe, 0x5a, + 0xff, 0x3a, 0x0e, 0x1b, 0x1c, 0x51, 0x2d, 0xe3, 0x81, 0xff, 0x7c, 0x6f, 0x12, 0x4d, 0xef, 0xee, + 0x6f, 0x04, 0xb2, 0xa7, 0x3c, 0xba, 0x0e, 0x43, 0xb5, 0x86, 0x4b, 0xbc, 0xa8, 0x5c, 0xe9, 0x14, + 0xc2, 0x70, 0x49, 0xd0, 0x88, 0x35, 0x24, 0x52, 0x6c, 0x70, 0x18, 0x56, 0x1c, 0xec, 0x5f, 0x2d, + 0xc0, 0x6c, 0x97, 0x7c, 0x2d, 0x09, 0x73, 0x94, 0xd5, 0x93, 0x39, 0x6a, 0x01, 0xc6, 0xe3, 0x7f, + 0xba, 0xa6, 0x4b, 0x79, 0xb4, 0xde, 0x32, 0xd1, 0x38, 0x49, 0xdf, 0xf3, 0xe3, 0x04, 0xdd, 0xa2, + 0xd5, 0xd7, 0xf5, 0x79, 0x8d, 0x61, 0xc9, 0xee, 0xef, 0xfd, 0xfa, 0x9b, 0x6b, 0x95, 0xb4, 0xbf, + 0x56, 0x80, 0xd3, 0xaa, 0x0b, 0xbf, 0x7d, 0x3b, 0xee, 0x66, 0xba, 0xe3, 0x8e, 0xc1, 0xa6, 0x6b, + 0xdf, 0x80, 0x01, 0x1e, 0x93, 0xb1, 0x07, 0xb1, 0xfb, 0x31, 0x33, 0x52, 0xb3, 0x92, 0xf4, 0x8c, + 0x68, 0xcd, 0xdf, 0x6f, 0xc1, 0x78, 0xe2, 0x95, 0x1b, 0xc2, 0xda, 0x53, 0xe8, 0xfb, 0x11, 0x8d, + 0xb3, 0x84, 0xee, 0x0b, 0xd0, 0xb7, 0xe3, 0x87, 0x51, 0xd2, 0xe1, 0xe3, 0xaa, 0x1f, 0x46, 0x98, + 0x61, 0xec, 0xdf, 0xb1, 0xa0, 0x7f, 0xc3, 0x71, 0xbd, 0x48, 0x1a, 0x07, 0xac, 0x1c, 0xe3, 0x40, + 0x2f, 0xdf, 0x85, 0x5e, 0x84, 0x01, 0xb2, 0xb5, 0x45, 0x6a, 0x91, 0x18, 0x55, 0x19, 0x47, 0x62, + 0x60, 0x85, 0x41, 0xa9, 0x1c, 0xc8, 0x2a, 0xe3, 0x7f, 0xb1, 0x20, 0x46, 0xb7, 0xa1, 0x14, 0xb9, + 0x4d, 0xb2, 0x50, 0xaf, 0x0b, 0x93, 0xf9, 0x7d, 0xc4, 0xc2, 0xd8, 0x90, 0x0c, 0x70, 0xcc, 0xcb, + 0xfe, 0x42, 0x01, 0x20, 0x0e, 0x66, 0xd5, 0xed, 0x13, 0x17, 0x53, 0xc6, 0xd4, 0x8b, 0x19, 0xc6, + 0x54, 0x14, 0x33, 0xcc, 0xb0, 0xa4, 0xaa, 0x6e, 0x2a, 0xf6, 0xd4, 0x4d, 0x7d, 0x47, 0xe9, 0xa6, + 0x25, 0x98, 0x8c, 0x83, 0x71, 0x99, 0xb1, 0x08, 0xd9, 0xf1, 0xb9, 0x91, 0x44, 0xe2, 0x34, 0xbd, + 0x4d, 0xe0, 0x82, 0x8a, 0x49, 0x24, 0x4e, 0x34, 0xe6, 0x0f, 0xae, 0x1b, 0xa7, 0xbb, 0xf4, 0x53, + 0x6c, 0x2d, 0x2e, 0xe4, 0x5a, 0x8b, 0x7f, 0xc2, 0x82, 0x53, 0xc9, 0x7a, 0xd8, 0xe3, 0xe9, 0xcf, + 0x5b, 0x70, 0x9a, 0xd9, 0xcc, 0x59, 0xad, 0x69, 0x0b, 0xfd, 0x0b, 0x1d, 0xe3, 0x2c, 0xe5, 0xb4, + 0x38, 0x0e, 0x58, 0xb2, 0x96, 0xc5, 0x1a, 0x67, 0xd7, 0x68, 0xff, 0xaf, 0x3e, 0x98, 0xce, 0x0b, + 0xd0, 0xc4, 0x9e, 0x8b, 0x38, 0x77, 0xab, 0xbb, 0xe4, 0x8e, 0x70, 0xca, 0x8f, 0x9f, 0x8b, 0x70, + 0x30, 0x96, 0xf8, 0x64, 0x0a, 0x8e, 0x42, 0x8f, 0x29, 0x38, 0x76, 0x60, 0xf2, 0xce, 0x0e, 0xf1, + 0x6e, 0x7a, 0xa1, 0x13, 0xb9, 0xe1, 0x96, 0xcb, 0xec, 0xcb, 0x7c, 0xde, 0xc8, 0xbc, 0xbd, 0x93, + 0xb7, 0x93, 0x04, 0x87, 0x07, 0xb3, 0xe7, 0x0c, 0x40, 0xdc, 0x64, 0xbe, 0x91, 0xe0, 0x34, 0xd3, + 0x74, 0x06, 0x93, 0xbe, 0x07, 0x9c, 0xc1, 0xa4, 0xe9, 0x0a, 0xaf, 0x14, 0xf9, 0x16, 0x80, 0xdd, + 0x1c, 0xd7, 0x14, 0x14, 0x6b, 0x14, 0xe8, 0x13, 0x80, 0xf4, 0x0c, 0x4d, 0x46, 0x7c, 0xcc, 0x67, + 0xef, 0x1d, 0xcc, 0xa2, 0xf5, 0x14, 0xf6, 0xf0, 0x60, 0x76, 0x8a, 0x42, 0xcb, 0x1e, 0xbd, 0x81, + 0xc6, 0x41, 0xc5, 0x32, 0x18, 0xa1, 0xdb, 0x30, 0x41, 0xa1, 0x6c, 0x45, 0xc9, 0xe0, 0x9b, 0xfc, + 0xd6, 0xf8, 0xf4, 0xbd, 0x83, 0xd9, 0x89, 0xf5, 0x04, 0x2e, 0x8f, 0x75, 0x8a, 0x09, 0x7a, 0x19, + 0xc6, 0xe2, 0x79, 0x75, 0x8d, 0xec, 0xf3, 0x60, 0x37, 0x25, 0xae, 0xf8, 0x5e, 0x33, 0x30, 0x38, + 0x41, 0x69, 0x7f, 0xde, 0x82, 0xb3, 0xb9, 0x59, 0xc4, 0xd1, 0x25, 0x18, 0x72, 0x5a, 0x2e, 0x37, + 0x63, 0x88, 0xa3, 0x86, 0xa9, 0xcb, 0x2a, 0x65, 0x6e, 0xc4, 0x50, 0x58, 0xba, 0xc3, 0xef, 0xba, + 0x5e, 0x3d, 0xb9, 0xc3, 0x5f, 0x73, 0xbd, 0x3a, 0x66, 0x18, 0x75, 0x64, 0x15, 0x73, 0x9f, 0x24, + 0x7c, 0x85, 0xae, 0xd5, 0x8c, 0x7c, 0xe3, 0x27, 0xdb, 0x0c, 0xf4, 0xb4, 0x6e, 0x72, 0x14, 0xde, + 0x85, 0xb9, 0xe6, 0xc6, 0xef, 0xb3, 0x40, 0x3c, 0x61, 0xee, 0xe1, 0x4c, 0xfe, 0x18, 0x8c, 0xec, + 0xa5, 0xb3, 0xd7, 0x5d, 0xc8, 0x7f, 0xd3, 0x2d, 0xa2, 0x7e, 0x2b, 0x41, 0xdb, 0xc8, 0x54, 0x67, + 0xf0, 0xb2, 0xeb, 0x20, 0xb0, 0xcb, 0x84, 0x19, 0x16, 0xba, 0xb7, 0xe6, 0x39, 0x80, 0x3a, 0xa3, + 0x65, 0x29, 0x6d, 0x0b, 0xa6, 0xc4, 0xb5, 0xac, 0x30, 0x58, 0xa3, 0xb2, 0xff, 0x75, 0x01, 0x86, + 0x65, 0xb6, 0xb4, 0xb6, 0xd7, 0x8b, 0xfa, 0xef, 0x48, 0xe9, 0x93, 0xd1, 0x3c, 0x94, 0x98, 0x7e, + 0xba, 0x12, 0x6b, 0x4d, 0x95, 0x76, 0x68, 0x4d, 0x22, 0x70, 0x4c, 0x43, 0x77, 0xc7, 0xb0, 0xbd, + 0xc9, 0xc8, 0x13, 0x0f, 0x6e, 0xab, 0x1c, 0x8c, 0x25, 0x1e, 0x7d, 0x04, 0x26, 0x78, 0xb9, 0xc0, + 0x6f, 0x39, 0xdb, 0xdc, 0xa6, 0xd5, 0xaf, 0xa2, 0x98, 0x4c, 0xac, 0x25, 0x70, 0x87, 0x07, 0xb3, + 0xa7, 0x92, 0x30, 0x66, 0xac, 0x4d, 0x71, 0x61, 0xae, 0x6b, 0xbc, 0x12, 0xba, 0xab, 0xa7, 0x3c, + 0xde, 0x62, 0x14, 0xd6, 0xe9, 0xec, 0x4f, 0x01, 0x4a, 0xe7, 0x8d, 0x43, 0xaf, 0x71, 0xd7, 0x67, + 0x37, 0x20, 0xf5, 0x4e, 0xc6, 0x5b, 0x3d, 0x56, 0x87, 0x7c, 0x2b, 0xc7, 0x4b, 0x61, 0x55, 0xde, + 0xfe, 0x0b, 0x45, 0x98, 0x48, 0x46, 0x07, 0x40, 0x57, 0x61, 0x80, 0x8b, 0x94, 0x82, 0x7d, 0x07, + 0xdf, 0x20, 0x2d, 0xa6, 0x00, 0x3b, 0x5c, 0x85, 0x54, 0x2a, 0xca, 0xa3, 0x37, 0x60, 0xb8, 0xee, + 0xdf, 0xf1, 0xee, 0x38, 0x41, 0x7d, 0xa1, 0x52, 0x16, 0xd3, 0x39, 0x53, 0x59, 0xb1, 0x1c, 0x93, + 0xe9, 0x71, 0x0a, 0x98, 0x1d, 0x3c, 0x46, 0x61, 0x9d, 0x1d, 0xda, 0x60, 0xc9, 0x26, 0xb6, 0xdc, + 0xed, 0x35, 0xa7, 0xd5, 0xe9, 0x1d, 0xcc, 0x92, 0x24, 0xd2, 0x38, 0x8f, 0x8a, 0x8c, 0x14, 0x1c, + 0x81, 0x63, 0x46, 0xe8, 0x33, 0x30, 0x15, 0xe6, 0x98, 0x50, 0xf2, 0xd2, 0x88, 0x76, 0xb2, 0x2a, + 0x2c, 0x3e, 0x74, 0xef, 0x60, 0x76, 0x2a, 0xcb, 0xd8, 0x92, 0x55, 0x8d, 0xfd, 0xc5, 0x53, 0x60, + 0x2c, 0x62, 0x23, 0xab, 0xb4, 0x75, 0x4c, 0x59, 0xa5, 0x31, 0x0c, 0x91, 0x66, 0x2b, 0xda, 0x5f, + 0x76, 0x03, 0x31, 0x26, 0x99, 0x3c, 0x57, 0x04, 0x4d, 0x9a, 0xa7, 0xc4, 0x60, 0xc5, 0x27, 0x3b, + 0xf5, 0x77, 0xf1, 0x9b, 0x98, 0xfa, 0xbb, 0xef, 0x04, 0x53, 0x7f, 0xaf, 0xc3, 0xe0, 0xb6, 0x1b, + 0x61, 0xd2, 0xf2, 0xc5, 0x65, 0x2e, 0x73, 0x1e, 0x5e, 0xe1, 0x24, 0xe9, 0x24, 0xb3, 0x02, 0x81, + 0x25, 0x13, 0xf4, 0x9a, 0x5a, 0x81, 0x03, 0xf9, 0x0a, 0x97, 0xb4, 0x13, 0x4b, 0xe6, 0x1a, 0x14, + 0x09, 0xbe, 0x07, 0xef, 0x37, 0xc1, 0xf7, 0xaa, 0x4c, 0xcb, 0x3d, 0x94, 0xff, 0x68, 0x8d, 0x65, + 0xdd, 0xee, 0x92, 0x8c, 0xfb, 0x96, 0x9e, 0xca, 0xbc, 0x94, 0xbf, 0x13, 0xa8, 0x2c, 0xe5, 0x3d, + 0x26, 0x30, 0xff, 0x3e, 0x0b, 0x4e, 0xb7, 0xb2, 0xb2, 0xfa, 0x0b, 0x7f, 0x8f, 0x17, 0x7b, 0xc9, + 0xfd, 0xca, 0x0a, 0x18, 0x15, 0x32, 0x3d, 0x69, 0x26, 0x19, 0xce, 0xae, 0x8e, 0x76, 0x74, 0xb0, + 0x59, 0x17, 0x7e, 0x07, 0x8f, 0xe5, 0x64, 0x42, 0xef, 0x90, 0xff, 0x7c, 0x23, 0x23, 0xeb, 0xf6, + 0xe3, 0x79, 0x59, 0xb7, 0x7b, 0xce, 0xb5, 0xfd, 0x9a, 0xca, 0x81, 0x3e, 0x9a, 0x3f, 0x95, 0x78, + 0x86, 0xf3, 0xae, 0x99, 0xcf, 0x5f, 0x53, 0x99, 0xcf, 0x3b, 0x84, 0xd7, 0xe6, 0x79, 0xcd, 0xbb, + 0xe6, 0x3b, 0xd7, 0x72, 0x96, 0x8f, 0x1f, 0x4f, 0xce, 0x72, 0xe3, 0xa8, 0xe1, 0x69, 0xb3, 0x9f, + 0xee, 0x72, 0xd4, 0x18, 0x7c, 0x3b, 0x1f, 0x36, 0x3c, 0x3f, 0xfb, 0xe4, 0x7d, 0xe5, 0x67, 0xbf, + 0xa5, 0xe7, 0x3b, 0x47, 0x5d, 0x12, 0x7a, 0x53, 0xa2, 0x1e, 0xb3, 0x9c, 0xdf, 0xd2, 0x0f, 0xc0, + 0xa9, 0x7c, 0xbe, 0xea, 0x9c, 0x4b, 0xf3, 0xcd, 0x3c, 0x02, 0x53, 0xd9, 0xd3, 0x4f, 0x9d, 0x4c, + 0xf6, 0xf4, 0xd3, 0xc7, 0x9e, 0x3d, 0xfd, 0xcc, 0x09, 0x64, 0x4f, 0x7f, 0xe8, 0x04, 0xb3, 0xa7, + 0xdf, 0x62, 0x4e, 0x52, 0x3c, 0x10, 0x94, 0x08, 0x07, 0xfe, 0x54, 0x4e, 0x1c, 0xb5, 0x74, 0xb4, + 0x28, 0xfe, 0x71, 0x0a, 0x85, 0x63, 0x56, 0x19, 0x59, 0xd9, 0xa7, 0x1f, 0x40, 0x56, 0xf6, 0xf5, + 0x38, 0x2b, 0xfb, 0xd9, 0xfc, 0xa1, 0xce, 0x78, 0x56, 0x93, 0x93, 0x8b, 0xfd, 0x96, 0x9e, 0x43, + 0xfd, 0xe1, 0x0e, 0x96, 0xb0, 0x2c, 0x85, 0x72, 0x87, 0xcc, 0xe9, 0xaf, 0xf2, 0xcc, 0xe9, 0x8f, + 0xe4, 0xef, 0xe4, 0xc9, 0xe3, 0xce, 0xc8, 0x97, 0x4e, 0xdb, 0xa5, 0x02, 0xa9, 0xb2, 0xc0, 0xe7, + 0x39, 0xed, 0x52, 0x91, 0x58, 0xd3, 0xed, 0x52, 0x28, 0x1c, 0xb3, 0xb2, 0x7f, 0xa0, 0x00, 0xe7, + 0x3b, 0xaf, 0xb7, 0x58, 0x4b, 0x5e, 0x89, 0x1d, 0x03, 0x12, 0x5a, 0x72, 0x7e, 0x67, 0x8b, 0xa9, + 0x7a, 0x8e, 0x0b, 0x79, 0x05, 0x26, 0xd5, 0x7b, 0x9c, 0x86, 0x5b, 0xdb, 0x5f, 0x8f, 0xaf, 0xc9, + 0x2a, 0x82, 0x42, 0x35, 0x49, 0x80, 0xd3, 0x65, 0xd0, 0x02, 0x8c, 0x1b, 0xc0, 0xf2, 0xb2, 0xb8, + 0x9b, 0xc5, 0xa1, 0xb6, 0x4d, 0x34, 0x4e, 0xd2, 0xdb, 0x5f, 0xb2, 0xe0, 0xa1, 0x9c, 0xb4, 0xa3, + 0x3d, 0x87, 0x3d, 0xdc, 0x82, 0xf1, 0x96, 0x59, 0xb4, 0x4b, 0xa4, 0x56, 0x23, 0xb9, 0xa9, 0x6a, + 0x6b, 0x02, 0x81, 0x93, 0x4c, 0xed, 0x9f, 0x2e, 0xc0, 0xb9, 0x8e, 0x0e, 0xa6, 0x08, 0xc3, 0x99, + 0xed, 0x66, 0xe8, 0x2c, 0x05, 0xa4, 0x4e, 0xbc, 0xc8, 0x75, 0x1a, 0xd5, 0x16, 0xa9, 0x69, 0x76, + 0x0e, 0xe6, 0xa9, 0x79, 0x65, 0xad, 0xba, 0x90, 0xa6, 0xc0, 0x39, 0x25, 0xd1, 0x2a, 0xa0, 0x34, + 0x46, 0x8c, 0x30, 0x0b, 0xa1, 0x9f, 0xe6, 0x87, 0x33, 0x4a, 0xa0, 0x0f, 0xc0, 0xa8, 0x72, 0x5c, + 0xd5, 0x46, 0x9c, 0x6d, 0xec, 0x58, 0x47, 0x60, 0x93, 0x0e, 0x5d, 0xe6, 0x39, 0x18, 0x44, 0xb6, + 0x0e, 0x61, 0x14, 0x19, 0x97, 0x09, 0x16, 0x04, 0x18, 0xeb, 0x34, 0x8b, 0x2f, 0xfd, 0xda, 0xef, + 0x9d, 0x7f, 0xcf, 0x6f, 0xfc, 0xde, 0xf9, 0xf7, 0xfc, 0xf6, 0xef, 0x9d, 0x7f, 0xcf, 0x77, 0xdd, + 0x3b, 0x6f, 0xfd, 0xda, 0xbd, 0xf3, 0xd6, 0x6f, 0xdc, 0x3b, 0x6f, 0xfd, 0xf6, 0xbd, 0xf3, 0xd6, + 0xef, 0xde, 0x3b, 0x6f, 0x7d, 0xe1, 0xf7, 0xcf, 0xbf, 0xe7, 0x63, 0x28, 0x0e, 0x24, 0x3a, 0x4f, + 0x47, 0x67, 0x7e, 0xef, 0xf2, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x52, 0x56, 0xa0, 0x3b, 0xf7, + 0x0c, 0x01, 0x00, } func (m *AWSElasticBlockStoreVolumeSource) Marshal() (dAtA []byte, err error) { @@ -8000,6 +8094,43 @@ func (m *CinderVolumeSource) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *ClaimSource) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ClaimSource) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ClaimSource) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ResourceClaimTemplateName != nil { + i -= len(*m.ResourceClaimTemplateName) + copy(dAtA[i:], *m.ResourceClaimTemplateName) + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.ResourceClaimTemplateName))) + i-- + dAtA[i] = 0x12 + } + if m.ResourceClaimName != nil { + i -= len(*m.ResourceClaimName) + copy(dAtA[i:], *m.ResourceClaimName) + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.ResourceClaimName))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *ClientIPConfig) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -14954,6 +15085,44 @@ func (m *PodReadinessGate) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *PodResourceClaim) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodResourceClaim) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodResourceClaim) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Source.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *PodSchedulingGate) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -15149,6 +15318,22 @@ func (m *PodSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.ResourceClaims) > 0 { + for iNdEx := len(m.ResourceClaims) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ResourceClaims[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2 + i-- + dAtA[i] = 0xba + } + } if len(m.SchedulingGates) > 0 { for iNdEx := len(m.SchedulingGates) - 1; iNdEx >= 0; iNdEx-- { { @@ -16794,6 +16979,34 @@ func (m *ReplicationControllerStatus) MarshalToSizedBuffer(dAtA []byte) (int, er return len(dAtA) - i, nil } +func (m *ResourceClaim) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClaim) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClaim) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *ResourceFieldSelector) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -17111,6 +17324,20 @@ func (m *ResourceRequirements) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Claims) > 0 { + for iNdEx := len(m.Claims) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Claims[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } if len(m.Requests) > 0 { keysForRequests := make([]string, 0, len(m.Requests)) for k := range m.Requests { @@ -20280,6 +20507,23 @@ func (m *CinderVolumeSource) Size() (n int) { return n } +func (m *ClaimSource) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ResourceClaimName != nil { + l = len(*m.ResourceClaimName) + n += 1 + l + sovGenerated(uint64(l)) + } + if m.ResourceClaimTemplateName != nil { + l = len(*m.ResourceClaimTemplateName) + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *ClientIPConfig) Size() (n int) { if m == nil { return 0 @@ -22819,6 +23063,19 @@ func (m *PodReadinessGate) Size() (n int) { return n } +func (m *PodResourceClaim) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + l = m.Source.Size() + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *PodSchedulingGate) Size() (n int) { if m == nil { return 0 @@ -23043,6 +23300,12 @@ func (m *PodSpec) Size() (n int) { n += 2 + l + sovGenerated(uint64(l)) } } + if len(m.ResourceClaims) > 0 { + for _, e := range m.ResourceClaims { + l = e.Size() + n += 2 + l + sovGenerated(uint64(l)) + } + } return n } @@ -23486,6 +23749,17 @@ func (m *ReplicationControllerStatus) Size() (n int) { return n } +func (m *ResourceClaim) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *ResourceFieldSelector) Size() (n int) { if m == nil { return 0 @@ -23612,6 +23886,12 @@ func (m *ResourceRequirements) Size() (n int) { n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) } } + if len(m.Claims) > 0 { + for _, e := range m.Claims { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -24871,6 +25151,17 @@ func (this *CinderVolumeSource) String() string { }, "") return s } +func (this *ClaimSource) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ClaimSource{`, + `ResourceClaimName:` + valueToStringGenerated(this.ResourceClaimName) + `,`, + `ResourceClaimTemplateName:` + valueToStringGenerated(this.ResourceClaimTemplateName) + `,`, + `}`, + }, "") + return s +} func (this *ClientIPConfig) String() string { if this == nil { return "nil" @@ -26811,6 +27102,17 @@ func (this *PodReadinessGate) String() string { }, "") return s } +func (this *PodResourceClaim) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PodResourceClaim{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Source:` + strings.Replace(strings.Replace(this.Source.String(), "ClaimSource", "ClaimSource", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} func (this *PodSchedulingGate) String() string { if this == nil { return "nil" @@ -26909,6 +27211,11 @@ func (this *PodSpec) String() string { repeatedStringForSchedulingGates += strings.Replace(strings.Replace(f.String(), "PodSchedulingGate", "PodSchedulingGate", 1), `&`, ``, 1) + "," } repeatedStringForSchedulingGates += "}" + repeatedStringForResourceClaims := "[]PodResourceClaim{" + for _, f := range this.ResourceClaims { + repeatedStringForResourceClaims += strings.Replace(strings.Replace(f.String(), "PodResourceClaim", "PodResourceClaim", 1), `&`, ``, 1) + "," + } + repeatedStringForResourceClaims += "}" keysForNodeSelector := make([]string, 0, len(this.NodeSelector)) for k := range this.NodeSelector { keysForNodeSelector = append(keysForNodeSelector, k) @@ -26968,6 +27275,7 @@ func (this *PodSpec) String() string { `OS:` + strings.Replace(this.OS.String(), "PodOS", "PodOS", 1) + `,`, `HostUsers:` + valueToStringGenerated(this.HostUsers) + `,`, `SchedulingGates:` + repeatedStringForSchedulingGates + `,`, + `ResourceClaims:` + repeatedStringForResourceClaims + `,`, `}`, }, "") return s @@ -27317,6 +27625,16 @@ func (this *ReplicationControllerStatus) String() string { }, "") return s } +func (this *ResourceClaim) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ResourceClaim{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `}`, + }, "") + return s +} func (this *ResourceFieldSelector) String() string { if this == nil { return "nil" @@ -27414,6 +27732,11 @@ func (this *ResourceRequirements) String() string { if this == nil { return "nil" } + repeatedStringForClaims := "[]ResourceClaim{" + for _, f := range this.Claims { + repeatedStringForClaims += strings.Replace(strings.Replace(f.String(), "ResourceClaim", "ResourceClaim", 1), `&`, ``, 1) + "," + } + repeatedStringForClaims += "}" keysForLimits := make([]string, 0, len(this.Limits)) for k := range this.Limits { keysForLimits = append(keysForLimits, string(k)) @@ -27437,6 +27760,7 @@ func (this *ResourceRequirements) String() string { s := strings.Join([]string{`&ResourceRequirements{`, `Limits:` + mapStringForLimits + `,`, `Requests:` + mapStringForRequests + `,`, + `Claims:` + repeatedStringForClaims + `,`, `}`, }, "") return s @@ -30994,6 +31318,122 @@ func (m *CinderVolumeSource) Unmarshal(dAtA []byte) error { } return nil } +func (m *ClaimSource) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ClaimSource: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ClaimSource: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResourceClaimName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := string(dAtA[iNdEx:postIndex]) + m.ResourceClaimName = &s + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResourceClaimTemplateName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := string(dAtA[iNdEx:postIndex]) + m.ResourceClaimTemplateName = &s + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *ClientIPConfig) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -52912,6 +53352,121 @@ func (m *PodReadinessGate) Unmarshal(dAtA []byte) error { } return nil } +func (m *PodResourceClaim) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodResourceClaim: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodResourceClaim: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Source", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Source.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *PodSchedulingGate) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -54810,6 +55365,40 @@ func (m *PodSpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 39: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResourceClaims", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ResourceClaims = append(m.ResourceClaims, PodResourceClaim{}) + if err := m.ResourceClaims[len(m.ResourceClaims)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -58788,6 +59377,88 @@ func (m *ReplicationControllerStatus) Unmarshal(dAtA []byte) error { } return nil } +func (m *ResourceClaim) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClaim: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClaim: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *ResourceFieldSelector) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -60043,6 +60714,40 @@ func (m *ResourceRequirements) Unmarshal(dAtA []byte) error { } m.Requests[ResourceName(mapkey)] = *mapvalue iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Claims", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Claims = append(m.Claims, ResourceClaim{}) + if err := m.Claims[len(m.Claims)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index 36ed2e2afaf..854bcdeba02 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -400,6 +400,36 @@ message CinderVolumeSource { optional LocalObjectReference secretRef = 4; } +// ClaimSource describes a reference to a ResourceClaim. +// +// Exactly one of these fields should be set. Consumers of this type must +// treat an empty object as if it has an unknown value. +message ClaimSource { + // ResourceClaimName is the name of a ResourceClaim object in the same + // namespace as this pod. + optional string resourceClaimName = 1; + + // ResourceClaimTemplateName is the name of a ResourceClaimTemplate + // object in the same namespace as this pod. + // + // The template will be used to create a new ResourceClaim, which will + // be bound to this pod. When this pod is deleted, the ResourceClaim + // will also be deleted. The name of the ResourceClaim will be -, where is the + // PodResourceClaim.Name. Pod validation will reject the pod if the + // concatenated name is not valid for a ResourceClaim (e.g. too long). + // + // An existing ResourceClaim with that name that is not owned by the + // pod will not be used for the pod to avoid using an unrelated + // resource by mistake. Scheduling and pod startup are then blocked + // until the unrelated ResourceClaim is removed. + // + // This field is immutable and no changes will be made to the + // corresponding ResourceClaim by the control plane after creating the + // ResourceClaim. + optional string resourceClaimTemplateName = 2; +} + // ClientIPConfig represents the configurations of Client IP based session affinity. message ClientIPConfig { // timeoutSeconds specifies the seconds of ClientIP type session sticky time. @@ -3360,6 +3390,18 @@ message PodReadinessGate { optional string conditionType = 1; } +// PodResourceClaim references exactly one ResourceClaim through a ClaimSource. +// It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. +// Containers that need access to the ResourceClaim reference it with this name. +message PodResourceClaim { + // Name uniquely identifies this resource claim inside the pod. + // This must be a DNS_LABEL. + optional string name = 1; + + // Source describes where to find the ResourceClaim. + optional ClaimSource source = 2; +} + // PodSchedulingGate is associated to a Pod to guard its scheduling. message PodSchedulingGate { // Name of the scheduling gate. @@ -3775,6 +3817,24 @@ message PodSpec { // +listType=map // +listMapKey=name repeated PodSchedulingGate schedulingGates = 38; + + // ResourceClaims defines which ResourceClaims must be allocated + // and reserved before the Pod is allowed to start. The resources + // will be made available to those containers which consume them + // by name. + // + // This is an alpha field and requires enabling the + // DynamicResourceAllocation feature gate. + // + // This field is immutable. + // + // +patchMergeKey=name + // +patchStrategy=merge,retainKeys + // +listType=map + // +listMapKey=name + // +featureGate=DynamicResourceAllocation + // +optional + repeated PodResourceClaim resourceClaims = 39; } // PodStatus represents information about the status of a pod. Status may trail the actual @@ -4348,6 +4408,14 @@ message ReplicationControllerStatus { repeated ReplicationControllerCondition conditions = 6; } +// ResourceClaim references one entry in PodSpec.ResourceClaims. +message ResourceClaim { + // Name must match the name of one entry in pod.spec.resourceClaims of + // the Pod where this field is used. It makes that resource available + // inside a container. + optional string name = 1; +} + // ResourceFieldSelector represents container resources (cpu, memory) and their output format // +structType=atomic message ResourceFieldSelector { @@ -4437,6 +4505,19 @@ message ResourceRequirements { // More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ // +optional map requests = 2; + + // Claims lists the names of resources, defined in spec.resourceClaims, + // that are used by this container. + // + // This is an alpha field and requires enabling the + // DynamicResourceAllocation feature gate. + // + // This field is immutable. + // + // +listType=set + // +featureGate=DynamicResourceAllocation + // +optional + repeated ResourceClaim claims = 3; } // SELinuxOptions are the labels to be applied to the container diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index 0b8ecc6b270..87230fd9181 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -2314,6 +2314,26 @@ type ResourceRequirements struct { // More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ // +optional Requests ResourceList `json:"requests,omitempty" protobuf:"bytes,2,rep,name=requests,casttype=ResourceList,castkey=ResourceName"` + // Claims lists the names of resources, defined in spec.resourceClaims, + // that are used by this container. + // + // This is an alpha field and requires enabling the + // DynamicResourceAllocation feature gate. + // + // This field is immutable. + // + // +listType=set + // +featureGate=DynamicResourceAllocation + // +optional + Claims []ResourceClaim `json:"claims,omitempty" protobuf:"bytes,3,opt,name=claims"` +} + +// ResourceClaim references one entry in PodSpec.ResourceClaims. +type ResourceClaim struct { + // Name must match the name of one entry in pod.spec.resourceClaims of + // the Pod where this field is used. It makes that resource available + // inside a container. + Name string `json:"name" protobuf:"bytes,1,opt,name=name"` } const ( @@ -3347,6 +3367,7 @@ type PodSpec struct { // - spec.containers[*].securityContext.runAsGroup // +optional OS *PodOS `json:"os,omitempty" protobuf:"bytes,36,opt,name=os"` + // Use the host's user namespace. // Optional: Default to true. // If set to true or not present, the pod will be run in the host user namespace, useful @@ -3359,6 +3380,7 @@ type PodSpec struct { // +k8s:conversion-gen=false // +optional HostUsers *bool `json:"hostUsers,omitempty" protobuf:"bytes,37,opt,name=hostUsers"` + // SchedulingGates is an opaque list of values that if specified will block scheduling the pod. // More info: https://git.k8s.io/enhancements/keps/sig-scheduling/3521-pod-scheduling-readiness. // @@ -3369,6 +3391,65 @@ type PodSpec struct { // +listType=map // +listMapKey=name SchedulingGates []PodSchedulingGate `json:"schedulingGates,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,38,opt,name=schedulingGates"` + // ResourceClaims defines which ResourceClaims must be allocated + // and reserved before the Pod is allowed to start. The resources + // will be made available to those containers which consume them + // by name. + // + // This is an alpha field and requires enabling the + // DynamicResourceAllocation feature gate. + // + // This field is immutable. + // + // +patchMergeKey=name + // +patchStrategy=merge,retainKeys + // +listType=map + // +listMapKey=name + // +featureGate=DynamicResourceAllocation + // +optional + ResourceClaims []PodResourceClaim `json:"resourceClaims,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name" protobuf:"bytes,39,rep,name=resourceClaims"` +} + +// PodResourceClaim references exactly one ResourceClaim through a ClaimSource. +// It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. +// Containers that need access to the ResourceClaim reference it with this name. +type PodResourceClaim struct { + // Name uniquely identifies this resource claim inside the pod. + // This must be a DNS_LABEL. + Name string `json:"name" protobuf:"bytes,1,name=name"` + + // Source describes where to find the ResourceClaim. + Source ClaimSource `json:"source,omitempty" protobuf:"bytes,2,name=source"` +} + +// ClaimSource describes a reference to a ResourceClaim. +// +// Exactly one of these fields should be set. Consumers of this type must +// treat an empty object as if it has an unknown value. +type ClaimSource struct { + // ResourceClaimName is the name of a ResourceClaim object in the same + // namespace as this pod. + ResourceClaimName *string `json:"resourceClaimName,omitempty" protobuf:"bytes,1,opt,name=resourceClaimName"` + + // ResourceClaimTemplateName is the name of a ResourceClaimTemplate + // object in the same namespace as this pod. + // + // The template will be used to create a new ResourceClaim, which will + // be bound to this pod. When this pod is deleted, the ResourceClaim + // will also be deleted. The name of the ResourceClaim will be -, where is the + // PodResourceClaim.Name. Pod validation will reject the pod if the + // concatenated name is not valid for a ResourceClaim (e.g. too long). + // + // An existing ResourceClaim with that name that is not owned by the + // pod will not be used for the pod to avoid using an unrelated + // resource by mistake. Scheduling and pod startup are then blocked + // until the unrelated ResourceClaim is removed. + // + // This field is immutable and no changes will be made to the + // corresponding ResourceClaim by the control plane after creating the + // ResourceClaim. + ResourceClaimTemplateName *string `json:"resourceClaimTemplateName,omitempty" protobuf:"bytes,2,opt,name=resourceClaimTemplateName"` } // OSName is the set of OS'es that can be used in OS. diff --git a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go index 10db6717770..6c6fe2e0064 100644 --- a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go @@ -209,6 +209,16 @@ func (CinderVolumeSource) SwaggerDoc() map[string]string { return map_CinderVolumeSource } +var map_ClaimSource = map[string]string{ + "": "ClaimSource describes a reference to a ResourceClaim.\n\nExactly one of these fields should be set. Consumers of this type must treat an empty object as if it has an unknown value.", + "resourceClaimName": "ResourceClaimName is the name of a ResourceClaim object in the same namespace as this pod.", + "resourceClaimTemplateName": "ResourceClaimTemplateName is the name of a ResourceClaimTemplate object in the same namespace as this pod.\n\nThe template will be used to create a new ResourceClaim, which will be bound to this pod. When this pod is deleted, the ResourceClaim will also be deleted. The name of the ResourceClaim will be -, where is the PodResourceClaim.Name. Pod validation will reject the pod if the concatenated name is not valid for a ResourceClaim (e.g. too long).\n\nAn existing ResourceClaim with that name that is not owned by the pod will not be used for the pod to avoid using an unrelated resource by mistake. Scheduling and pod startup are then blocked until the unrelated ResourceClaim is removed.\n\nThis field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim.", +} + +func (ClaimSource) SwaggerDoc() map[string]string { + return map_ClaimSource +} + var map_ClientIPConfig = map[string]string{ "": "ClientIPConfig represents the configurations of Client IP based session affinity.", "timeoutSeconds": "timeoutSeconds specifies the seconds of ClientIP type session sticky time. The value must be >0 && <=86400(for 1 day) if ServiceAffinity == \"ClientIP\". Default value is 10800(for 3 hours).", @@ -1606,6 +1616,16 @@ func (PodReadinessGate) SwaggerDoc() map[string]string { return map_PodReadinessGate } +var map_PodResourceClaim = map[string]string{ + "": "PodResourceClaim references exactly one ResourceClaim through a ClaimSource. It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name.", + "name": "Name uniquely identifies this resource claim inside the pod. This must be a DNS_LABEL.", + "source": "Source describes where to find the ResourceClaim.", +} + +func (PodResourceClaim) SwaggerDoc() map[string]string { + return map_PodResourceClaim +} + var map_PodSchedulingGate = map[string]string{ "": "PodSchedulingGate is associated to a Pod to guard its scheduling.", "name": "Name of the scheduling gate. Each scheduling gate must have a unique name field.", @@ -1682,6 +1702,7 @@ var map_PodSpec = map[string]string{ "os": "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.hostUsers - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup", "hostUsers": "Use the host's user namespace. Optional: Default to true. If set to true or not present, the pod will be run in the host user namespace, useful for when the pod needs a feature only available to the host user namespace, such as loading a kernel module with CAP_SYS_MODULE. When set to false, a new userns is created for the pod. Setting false is useful for mitigating container breakout vulnerabilities even allowing users to run their containers as root without actually having root privileges on the host. This field is alpha-level and is only honored by servers that enable the UserNamespacesSupport feature.", "schedulingGates": "SchedulingGates is an opaque list of values that if specified will block scheduling the pod. More info: https://git.k8s.io/enhancements/keps/sig-scheduling/3521-pod-scheduling-readiness.\n\nThis is an alpha-level feature enabled by PodSchedulingReadiness feature gate.", + "resourceClaims": "ResourceClaims defines which ResourceClaims must be allocated and reserved before the Pod is allowed to start. The resources will be made available to those containers which consume them by name.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", } func (PodSpec) SwaggerDoc() map[string]string { @@ -1954,6 +1975,15 @@ func (ReplicationControllerStatus) SwaggerDoc() map[string]string { return map_ReplicationControllerStatus } +var map_ResourceClaim = map[string]string{ + "": "ResourceClaim references one entry in PodSpec.ResourceClaims.", + "name": "Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container.", +} + +func (ResourceClaim) SwaggerDoc() map[string]string { + return map_ResourceClaim +} + var map_ResourceFieldSelector = map[string]string{ "": "ResourceFieldSelector represents container resources (cpu, memory) and their output format", "containerName": "Container name: required for volumes, optional for env vars", @@ -2011,6 +2041,7 @@ var map_ResourceRequirements = map[string]string{ "": "ResourceRequirements describes the compute resource requirements.", "limits": "Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/", "requests": "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/", + "claims": "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", } func (ResourceRequirements) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go index 59efcdf216e..2bf1c8ad648 100644 --- a/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go @@ -419,6 +419,32 @@ func (in *CinderVolumeSource) DeepCopy() *CinderVolumeSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClaimSource) DeepCopyInto(out *ClaimSource) { + *out = *in + if in.ResourceClaimName != nil { + in, out := &in.ResourceClaimName, &out.ResourceClaimName + *out = new(string) + **out = **in + } + if in.ResourceClaimTemplateName != nil { + in, out := &in.ResourceClaimTemplateName, &out.ResourceClaimTemplateName + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimSource. +func (in *ClaimSource) DeepCopy() *ClaimSource { + if in == nil { + return nil + } + out := new(ClaimSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClientIPConfig) DeepCopyInto(out *ClientIPConfig) { *out = *in @@ -3726,6 +3752,23 @@ func (in *PodReadinessGate) DeepCopy() *PodReadinessGate { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodResourceClaim) DeepCopyInto(out *PodResourceClaim) { + *out = *in + in.Source.DeepCopyInto(&out.Source) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodResourceClaim. +func (in *PodResourceClaim) DeepCopy() *PodResourceClaim { + if in == nil { + return nil + } + out := new(PodResourceClaim) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PodSchedulingGate) DeepCopyInto(out *PodSchedulingGate) { *out = *in @@ -3980,6 +4023,13 @@ func (in *PodSpec) DeepCopyInto(out *PodSpec) { *out = make([]PodSchedulingGate, len(*in)) copy(*out, *in) } + if in.ResourceClaims != nil { + in, out := &in.ResourceClaims, &out.ResourceClaims + *out = make([]PodResourceClaim, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -4563,6 +4613,22 @@ func (in *ReplicationControllerStatus) DeepCopy() *ReplicationControllerStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaim) DeepCopyInto(out *ResourceClaim) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaim. +func (in *ResourceClaim) DeepCopy() *ResourceClaim { + if in == nil { + return nil + } + out := new(ResourceClaim) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceFieldSelector) DeepCopyInto(out *ResourceFieldSelector) { *out = *in @@ -4743,6 +4809,11 @@ func (in *ResourceRequirements) DeepCopyInto(out *ResourceRequirements) { (*out)[key] = val.DeepCopy() } } + if in.Claims != nil { + in, out := &in.Claims, &out.Claims + *out = make([]ResourceClaim, len(*in)) + copy(*out, *in) + } return } diff --git a/staging/src/k8s.io/api/resource/OWNERS b/staging/src/k8s.io/api/resource/OWNERS new file mode 100644 index 00000000000..98397072ae5 --- /dev/null +++ b/staging/src/k8s.io/api/resource/OWNERS @@ -0,0 +1,6 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +reviewers: + - bart0sh + - klueska + - pohly diff --git a/staging/src/k8s.io/api/resource/v1alpha1/doc.go b/staging/src/k8s.io/api/resource/v1alpha1/doc.go new file mode 100644 index 00000000000..8fa577fabc8 --- /dev/null +++ b/staging/src/k8s.io/api/resource/v1alpha1/doc.go @@ -0,0 +1,24 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package +// +k8s:protobuf-gen=package + +// +groupName=resource.k8s.io + +// Package v1alpha1 is the v1alpha1 version of the resource API. +package v1alpha1 // import "k8s.io/api/resource/v1alpha1" diff --git a/staging/src/k8s.io/api/resource/v1alpha1/generated.pb.go b/staging/src/k8s.io/api/resource/v1alpha1/generated.pb.go new file mode 100644 index 00000000000..632ad04259e --- /dev/null +++ b/staging/src/k8s.io/api/resource/v1alpha1/generated.pb.go @@ -0,0 +1,4593 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: k8s.io/kubernetes/vendor/k8s.io/api/resource/v1alpha1/generated.proto + +package v1alpha1 + +import ( + fmt "fmt" + + io "io" + + proto "github.com/gogo/protobuf/proto" + v1 "k8s.io/api/core/v1" + + math "math" + math_bits "math/bits" + reflect "reflect" + strings "strings" + + k8s_io_apimachinery_pkg_types "k8s.io/apimachinery/pkg/types" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +func (m *AllocationResult) Reset() { *m = AllocationResult{} } +func (*AllocationResult) ProtoMessage() {} +func (*AllocationResult) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{0} +} +func (m *AllocationResult) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AllocationResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *AllocationResult) XXX_Merge(src proto.Message) { + xxx_messageInfo_AllocationResult.Merge(m, src) +} +func (m *AllocationResult) XXX_Size() int { + return m.Size() +} +func (m *AllocationResult) XXX_DiscardUnknown() { + xxx_messageInfo_AllocationResult.DiscardUnknown(m) +} + +var xxx_messageInfo_AllocationResult proto.InternalMessageInfo + +func (m *PodScheduling) Reset() { *m = PodScheduling{} } +func (*PodScheduling) ProtoMessage() {} +func (*PodScheduling) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{1} +} +func (m *PodScheduling) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodScheduling) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *PodScheduling) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodScheduling.Merge(m, src) +} +func (m *PodScheduling) XXX_Size() int { + return m.Size() +} +func (m *PodScheduling) XXX_DiscardUnknown() { + xxx_messageInfo_PodScheduling.DiscardUnknown(m) +} + +var xxx_messageInfo_PodScheduling proto.InternalMessageInfo + +func (m *PodSchedulingList) Reset() { *m = PodSchedulingList{} } +func (*PodSchedulingList) ProtoMessage() {} +func (*PodSchedulingList) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{2} +} +func (m *PodSchedulingList) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSchedulingList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *PodSchedulingList) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSchedulingList.Merge(m, src) +} +func (m *PodSchedulingList) XXX_Size() int { + return m.Size() +} +func (m *PodSchedulingList) XXX_DiscardUnknown() { + xxx_messageInfo_PodSchedulingList.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSchedulingList proto.InternalMessageInfo + +func (m *PodSchedulingSpec) Reset() { *m = PodSchedulingSpec{} } +func (*PodSchedulingSpec) ProtoMessage() {} +func (*PodSchedulingSpec) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{3} +} +func (m *PodSchedulingSpec) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSchedulingSpec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *PodSchedulingSpec) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSchedulingSpec.Merge(m, src) +} +func (m *PodSchedulingSpec) XXX_Size() int { + return m.Size() +} +func (m *PodSchedulingSpec) XXX_DiscardUnknown() { + xxx_messageInfo_PodSchedulingSpec.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSchedulingSpec proto.InternalMessageInfo + +func (m *PodSchedulingStatus) Reset() { *m = PodSchedulingStatus{} } +func (*PodSchedulingStatus) ProtoMessage() {} +func (*PodSchedulingStatus) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{4} +} +func (m *PodSchedulingStatus) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PodSchedulingStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *PodSchedulingStatus) XXX_Merge(src proto.Message) { + xxx_messageInfo_PodSchedulingStatus.Merge(m, src) +} +func (m *PodSchedulingStatus) XXX_Size() int { + return m.Size() +} +func (m *PodSchedulingStatus) XXX_DiscardUnknown() { + xxx_messageInfo_PodSchedulingStatus.DiscardUnknown(m) +} + +var xxx_messageInfo_PodSchedulingStatus proto.InternalMessageInfo + +func (m *ResourceClaim) Reset() { *m = ResourceClaim{} } +func (*ResourceClaim) ProtoMessage() {} +func (*ResourceClaim) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{5} +} +func (m *ResourceClaim) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClaim) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClaim) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClaim.Merge(m, src) +} +func (m *ResourceClaim) XXX_Size() int { + return m.Size() +} +func (m *ResourceClaim) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClaim.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClaim proto.InternalMessageInfo + +func (m *ResourceClaimConsumerReference) Reset() { *m = ResourceClaimConsumerReference{} } +func (*ResourceClaimConsumerReference) ProtoMessage() {} +func (*ResourceClaimConsumerReference) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{6} +} +func (m *ResourceClaimConsumerReference) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClaimConsumerReference) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClaimConsumerReference) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClaimConsumerReference.Merge(m, src) +} +func (m *ResourceClaimConsumerReference) XXX_Size() int { + return m.Size() +} +func (m *ResourceClaimConsumerReference) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClaimConsumerReference.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClaimConsumerReference proto.InternalMessageInfo + +func (m *ResourceClaimList) Reset() { *m = ResourceClaimList{} } +func (*ResourceClaimList) ProtoMessage() {} +func (*ResourceClaimList) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{7} +} +func (m *ResourceClaimList) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClaimList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClaimList) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClaimList.Merge(m, src) +} +func (m *ResourceClaimList) XXX_Size() int { + return m.Size() +} +func (m *ResourceClaimList) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClaimList.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClaimList proto.InternalMessageInfo + +func (m *ResourceClaimParametersReference) Reset() { *m = ResourceClaimParametersReference{} } +func (*ResourceClaimParametersReference) ProtoMessage() {} +func (*ResourceClaimParametersReference) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{8} +} +func (m *ResourceClaimParametersReference) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClaimParametersReference) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClaimParametersReference) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClaimParametersReference.Merge(m, src) +} +func (m *ResourceClaimParametersReference) XXX_Size() int { + return m.Size() +} +func (m *ResourceClaimParametersReference) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClaimParametersReference.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClaimParametersReference proto.InternalMessageInfo + +func (m *ResourceClaimSchedulingStatus) Reset() { *m = ResourceClaimSchedulingStatus{} } +func (*ResourceClaimSchedulingStatus) ProtoMessage() {} +func (*ResourceClaimSchedulingStatus) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{9} +} +func (m *ResourceClaimSchedulingStatus) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClaimSchedulingStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClaimSchedulingStatus) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClaimSchedulingStatus.Merge(m, src) +} +func (m *ResourceClaimSchedulingStatus) XXX_Size() int { + return m.Size() +} +func (m *ResourceClaimSchedulingStatus) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClaimSchedulingStatus.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClaimSchedulingStatus proto.InternalMessageInfo + +func (m *ResourceClaimSpec) Reset() { *m = ResourceClaimSpec{} } +func (*ResourceClaimSpec) ProtoMessage() {} +func (*ResourceClaimSpec) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{10} +} +func (m *ResourceClaimSpec) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClaimSpec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClaimSpec) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClaimSpec.Merge(m, src) +} +func (m *ResourceClaimSpec) XXX_Size() int { + return m.Size() +} +func (m *ResourceClaimSpec) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClaimSpec.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClaimSpec proto.InternalMessageInfo + +func (m *ResourceClaimStatus) Reset() { *m = ResourceClaimStatus{} } +func (*ResourceClaimStatus) ProtoMessage() {} +func (*ResourceClaimStatus) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{11} +} +func (m *ResourceClaimStatus) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClaimStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClaimStatus) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClaimStatus.Merge(m, src) +} +func (m *ResourceClaimStatus) XXX_Size() int { + return m.Size() +} +func (m *ResourceClaimStatus) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClaimStatus.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClaimStatus proto.InternalMessageInfo + +func (m *ResourceClaimTemplate) Reset() { *m = ResourceClaimTemplate{} } +func (*ResourceClaimTemplate) ProtoMessage() {} +func (*ResourceClaimTemplate) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{12} +} +func (m *ResourceClaimTemplate) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClaimTemplate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClaimTemplate) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClaimTemplate.Merge(m, src) +} +func (m *ResourceClaimTemplate) XXX_Size() int { + return m.Size() +} +func (m *ResourceClaimTemplate) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClaimTemplate.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClaimTemplate proto.InternalMessageInfo + +func (m *ResourceClaimTemplateList) Reset() { *m = ResourceClaimTemplateList{} } +func (*ResourceClaimTemplateList) ProtoMessage() {} +func (*ResourceClaimTemplateList) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{13} +} +func (m *ResourceClaimTemplateList) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClaimTemplateList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClaimTemplateList) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClaimTemplateList.Merge(m, src) +} +func (m *ResourceClaimTemplateList) XXX_Size() int { + return m.Size() +} +func (m *ResourceClaimTemplateList) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClaimTemplateList.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClaimTemplateList proto.InternalMessageInfo + +func (m *ResourceClaimTemplateSpec) Reset() { *m = ResourceClaimTemplateSpec{} } +func (*ResourceClaimTemplateSpec) ProtoMessage() {} +func (*ResourceClaimTemplateSpec) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{14} +} +func (m *ResourceClaimTemplateSpec) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClaimTemplateSpec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClaimTemplateSpec) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClaimTemplateSpec.Merge(m, src) +} +func (m *ResourceClaimTemplateSpec) XXX_Size() int { + return m.Size() +} +func (m *ResourceClaimTemplateSpec) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClaimTemplateSpec.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClaimTemplateSpec proto.InternalMessageInfo + +func (m *ResourceClass) Reset() { *m = ResourceClass{} } +func (*ResourceClass) ProtoMessage() {} +func (*ResourceClass) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{15} +} +func (m *ResourceClass) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClass) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClass) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClass.Merge(m, src) +} +func (m *ResourceClass) XXX_Size() int { + return m.Size() +} +func (m *ResourceClass) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClass.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClass proto.InternalMessageInfo + +func (m *ResourceClassList) Reset() { *m = ResourceClassList{} } +func (*ResourceClassList) ProtoMessage() {} +func (*ResourceClassList) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{16} +} +func (m *ResourceClassList) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClassList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClassList) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClassList.Merge(m, src) +} +func (m *ResourceClassList) XXX_Size() int { + return m.Size() +} +func (m *ResourceClassList) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClassList.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClassList proto.InternalMessageInfo + +func (m *ResourceClassParametersReference) Reset() { *m = ResourceClassParametersReference{} } +func (*ResourceClassParametersReference) ProtoMessage() {} +func (*ResourceClassParametersReference) Descriptor() ([]byte, []int) { + return fileDescriptor_a66b2ee03d862be2, []int{17} +} +func (m *ResourceClassParametersReference) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResourceClassParametersReference) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ResourceClassParametersReference) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResourceClassParametersReference.Merge(m, src) +} +func (m *ResourceClassParametersReference) XXX_Size() int { + return m.Size() +} +func (m *ResourceClassParametersReference) XXX_DiscardUnknown() { + xxx_messageInfo_ResourceClassParametersReference.DiscardUnknown(m) +} + +var xxx_messageInfo_ResourceClassParametersReference proto.InternalMessageInfo + +func init() { + proto.RegisterType((*AllocationResult)(nil), "k8s.io.api.resource.v1alpha1.AllocationResult") + proto.RegisterType((*PodScheduling)(nil), "k8s.io.api.resource.v1alpha1.PodScheduling") + proto.RegisterType((*PodSchedulingList)(nil), "k8s.io.api.resource.v1alpha1.PodSchedulingList") + proto.RegisterType((*PodSchedulingSpec)(nil), "k8s.io.api.resource.v1alpha1.PodSchedulingSpec") + proto.RegisterType((*PodSchedulingStatus)(nil), "k8s.io.api.resource.v1alpha1.PodSchedulingStatus") + proto.RegisterType((*ResourceClaim)(nil), "k8s.io.api.resource.v1alpha1.ResourceClaim") + proto.RegisterType((*ResourceClaimConsumerReference)(nil), "k8s.io.api.resource.v1alpha1.ResourceClaimConsumerReference") + proto.RegisterType((*ResourceClaimList)(nil), "k8s.io.api.resource.v1alpha1.ResourceClaimList") + proto.RegisterType((*ResourceClaimParametersReference)(nil), "k8s.io.api.resource.v1alpha1.ResourceClaimParametersReference") + proto.RegisterType((*ResourceClaimSchedulingStatus)(nil), "k8s.io.api.resource.v1alpha1.ResourceClaimSchedulingStatus") + proto.RegisterType((*ResourceClaimSpec)(nil), "k8s.io.api.resource.v1alpha1.ResourceClaimSpec") + proto.RegisterType((*ResourceClaimStatus)(nil), "k8s.io.api.resource.v1alpha1.ResourceClaimStatus") + proto.RegisterType((*ResourceClaimTemplate)(nil), "k8s.io.api.resource.v1alpha1.ResourceClaimTemplate") + proto.RegisterType((*ResourceClaimTemplateList)(nil), "k8s.io.api.resource.v1alpha1.ResourceClaimTemplateList") + proto.RegisterType((*ResourceClaimTemplateSpec)(nil), "k8s.io.api.resource.v1alpha1.ResourceClaimTemplateSpec") + proto.RegisterType((*ResourceClass)(nil), "k8s.io.api.resource.v1alpha1.ResourceClass") + proto.RegisterType((*ResourceClassList)(nil), "k8s.io.api.resource.v1alpha1.ResourceClassList") + proto.RegisterType((*ResourceClassParametersReference)(nil), "k8s.io.api.resource.v1alpha1.ResourceClassParametersReference") +} + +func init() { + proto.RegisterFile("k8s.io/kubernetes/vendor/k8s.io/api/resource/v1alpha1/generated.proto", fileDescriptor_a66b2ee03d862be2) +} + +var fileDescriptor_a66b2ee03d862be2 = []byte{ + // 1174 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcd, 0x6f, 0x1b, 0x45, + 0x14, 0xcf, 0xc6, 0x6e, 0x95, 0x8c, 0x1b, 0x37, 0xd9, 0x34, 0xc8, 0x8d, 0x5a, 0xdb, 0xec, 0xc9, + 0x12, 0xb0, 0xdb, 0x04, 0x04, 0x15, 0x1f, 0x95, 0xb2, 0x0d, 0x94, 0x08, 0x9a, 0x9a, 0x31, 0x91, + 0x08, 0x42, 0x88, 0xf1, 0xee, 0xab, 0xbd, 0x64, 0xbf, 0xd8, 0xd9, 0x35, 0xaa, 0xb8, 0xf4, 0xca, + 0x0d, 0x21, 0xee, 0x1c, 0xf9, 0x43, 0x10, 0x52, 0x8e, 0x91, 0xe0, 0xd0, 0x93, 0x45, 0xcc, 0x81, + 0x3f, 0x80, 0x13, 0x3d, 0xa1, 0x19, 0xef, 0xae, 0x77, 0xd6, 0x1f, 0xc4, 0x11, 0x8a, 0xc2, 0x29, + 0x99, 0x79, 0xbf, 0xf7, 0x9b, 0xf7, 0x31, 0xef, 0xcd, 0x5b, 0xa3, 0x77, 0x8f, 0xee, 0x52, 0xd5, + 0xf2, 0xb4, 0xa3, 0xa8, 0x0d, 0x81, 0x0b, 0x21, 0x50, 0xad, 0x07, 0xae, 0xe9, 0x05, 0x5a, 0x2c, + 0x20, 0xbe, 0xa5, 0x05, 0x40, 0xbd, 0x28, 0x30, 0x40, 0xeb, 0x6d, 0x11, 0xdb, 0xef, 0x92, 0x2d, + 0xad, 0x03, 0x2e, 0x04, 0x24, 0x04, 0x53, 0xf5, 0x03, 0x2f, 0xf4, 0xe4, 0x5b, 0x43, 0xb4, 0x4a, + 0x7c, 0x4b, 0x4d, 0xd0, 0x6a, 0x82, 0xde, 0x7c, 0xa5, 0x63, 0x85, 0xdd, 0xa8, 0xad, 0x1a, 0x9e, + 0xa3, 0x75, 0xbc, 0x8e, 0xa7, 0x71, 0xa5, 0x76, 0xf4, 0x98, 0xaf, 0xf8, 0x82, 0xff, 0x37, 0x24, + 0xdb, 0x54, 0x32, 0x47, 0x1b, 0x5e, 0xc0, 0x8e, 0xcd, 0x1f, 0xb8, 0xf9, 0xda, 0x08, 0xe3, 0x10, + 0xa3, 0x6b, 0xb9, 0x10, 0x3c, 0xd1, 0xfc, 0xa3, 0x0e, 0xdb, 0xa0, 0x9a, 0x03, 0x21, 0x99, 0xa4, + 0xa5, 0x4d, 0xd3, 0x0a, 0x22, 0x37, 0xb4, 0x1c, 0x18, 0x53, 0x78, 0xfd, 0xdf, 0x14, 0xa8, 0xd1, + 0x05, 0x87, 0xe4, 0xf5, 0x94, 0x3f, 0x25, 0xb4, 0xba, 0x63, 0xdb, 0x9e, 0x41, 0x42, 0xcb, 0x73, + 0x31, 0xd0, 0xc8, 0x0e, 0xe5, 0x7b, 0xa8, 0x9c, 0xc4, 0xe6, 0x7d, 0xe2, 0x9a, 0x36, 0x54, 0xa4, + 0xba, 0xd4, 0x58, 0xd6, 0x5f, 0x38, 0xee, 0xd7, 0x16, 0x06, 0xfd, 0x5a, 0x19, 0x0b, 0x52, 0x9c, + 0x43, 0xcb, 0x6d, 0xb4, 0x4a, 0x7a, 0xc4, 0xb2, 0x49, 0xdb, 0x86, 0x47, 0xee, 0xbe, 0x67, 0x02, + 0xad, 0x2c, 0xd6, 0xa5, 0x46, 0x69, 0xbb, 0xae, 0x66, 0xe2, 0xcf, 0x42, 0xa6, 0xf6, 0xb6, 0x54, + 0x06, 0x68, 0x81, 0x0d, 0x46, 0xe8, 0x05, 0xfa, 0x8d, 0x41, 0xbf, 0xb6, 0xba, 0x93, 0xd3, 0xc6, + 0x63, 0x7c, 0xb2, 0x86, 0x96, 0x69, 0x97, 0x04, 0xc0, 0xf6, 0x2a, 0x85, 0xba, 0xd4, 0x58, 0xd2, + 0xd7, 0x62, 0xf3, 0x96, 0x5b, 0x89, 0x00, 0x8f, 0x30, 0xca, 0x8f, 0x8b, 0x68, 0xa5, 0xe9, 0x99, + 0x2d, 0xa3, 0x0b, 0x66, 0x64, 0x5b, 0x6e, 0x47, 0xfe, 0x02, 0x2d, 0xb1, 0xf8, 0x9b, 0x24, 0x24, + 0xdc, 0xc1, 0xd2, 0xf6, 0x9d, 0x8c, 0x79, 0x69, 0x18, 0x55, 0xff, 0xa8, 0xc3, 0x36, 0xa8, 0xca, + 0xd0, 0xcc, 0xe0, 0x47, 0xed, 0x2f, 0xc1, 0x08, 0x1f, 0x42, 0x48, 0x74, 0x39, 0x3e, 0x13, 0x8d, + 0xf6, 0x70, 0xca, 0x2a, 0x7f, 0x84, 0x8a, 0xd4, 0x07, 0x23, 0x76, 0x5e, 0x53, 0x67, 0x5d, 0x3e, + 0x55, 0x30, 0xae, 0xe5, 0x83, 0xa1, 0x5f, 0x8b, 0xc9, 0x8b, 0x6c, 0x85, 0x39, 0x95, 0x7c, 0x88, + 0xae, 0xd2, 0x90, 0x84, 0x11, 0xe5, 0x4e, 0x97, 0xb6, 0xb7, 0xe6, 0x21, 0xe5, 0x8a, 0x7a, 0x39, + 0xa6, 0xbd, 0x3a, 0x5c, 0xe3, 0x98, 0x50, 0xf9, 0x59, 0x42, 0x6b, 0x02, 0xfe, 0x43, 0x8b, 0x86, + 0xf2, 0x67, 0x63, 0x51, 0x52, 0xcf, 0x16, 0x25, 0xa6, 0xcd, 0x63, 0xb4, 0x1a, 0x9f, 0xb7, 0x94, + 0xec, 0x64, 0x22, 0xd4, 0x44, 0x57, 0xac, 0x10, 0x1c, 0x76, 0x3f, 0x0a, 0x8d, 0xd2, 0xf6, 0x4b, + 0x73, 0x78, 0xa3, 0xaf, 0xc4, 0xbc, 0x57, 0xf6, 0x18, 0x03, 0x1e, 0x12, 0x29, 0xdf, 0xe6, 0xbd, + 0x60, 0xc1, 0x93, 0xef, 0xa2, 0x6b, 0x94, 0x5f, 0x31, 0x30, 0xd9, 0xfd, 0x89, 0x2f, 0xf4, 0x8d, + 0x98, 0xe1, 0x5a, 0x2b, 0x23, 0xc3, 0x02, 0x52, 0x7e, 0x13, 0x95, 0x7d, 0x2f, 0x04, 0x37, 0xb4, + 0x88, 0x9d, 0x5c, 0xe5, 0x42, 0x63, 0x59, 0x97, 0x59, 0x21, 0x34, 0x05, 0x09, 0xce, 0x21, 0x95, + 0xef, 0x25, 0xb4, 0x3e, 0x21, 0x03, 0xf2, 0x37, 0xa3, 0x02, 0xbb, 0x6f, 0x13, 0xcb, 0xa1, 0x15, + 0x89, 0xbb, 0xff, 0xd6, 0x6c, 0xf7, 0x71, 0x56, 0x67, 0x2c, 0xad, 0x63, 0xd5, 0x39, 0xa4, 0xc6, + 0xb9, 0xa3, 0x78, 0x21, 0x08, 0x90, 0xcb, 0x56, 0x08, 0xa2, 0x9b, 0xff, 0x51, 0x21, 0x88, 0xa4, + 0xb3, 0x0b, 0x61, 0x20, 0xa1, 0xaa, 0x80, 0xbf, 0xef, 0xb9, 0x34, 0x72, 0x20, 0xc0, 0xf0, 0x18, + 0x02, 0x70, 0x0d, 0x90, 0x5f, 0x46, 0x4b, 0xc4, 0xb7, 0x1e, 0x04, 0x5e, 0xe4, 0xc7, 0x77, 0x29, + 0xbd, 0xe5, 0x3b, 0xcd, 0x3d, 0xbe, 0x8f, 0x53, 0x04, 0x43, 0x27, 0x16, 0x71, 0x6b, 0x33, 0xe8, + 0xe4, 0x1c, 0x9c, 0x22, 0xe4, 0x3a, 0x2a, 0xba, 0xc4, 0x81, 0x4a, 0x91, 0x23, 0x53, 0xdf, 0xf7, + 0x89, 0x03, 0x98, 0x4b, 0x64, 0x1d, 0x15, 0x22, 0xcb, 0xac, 0x5c, 0xe1, 0x80, 0x3b, 0x31, 0xa0, + 0x70, 0xb0, 0xb7, 0xfb, 0xbc, 0x5f, 0x7b, 0x71, 0xda, 0x4b, 0x10, 0x3e, 0xf1, 0x81, 0xaa, 0x07, + 0x7b, 0xbb, 0x98, 0x29, 0xf3, 0x6a, 0x17, 0x9c, 0xbc, 0x74, 0xd5, 0x2e, 0x58, 0x37, 0xa5, 0xda, + 0x7f, 0x90, 0x50, 0x5d, 0xc0, 0x35, 0x49, 0x40, 0x1c, 0x08, 0x21, 0xa0, 0xe7, 0x4d, 0x56, 0x1d, + 0x15, 0x8f, 0x2c, 0xd7, 0xe4, 0x77, 0x35, 0x13, 0xfe, 0x0f, 0x2c, 0xd7, 0xc4, 0x5c, 0x92, 0x26, + 0xa8, 0x30, 0x2d, 0x41, 0xca, 0x53, 0x09, 0xdd, 0x9e, 0x59, 0xad, 0x29, 0x87, 0x34, 0x35, 0xc9, + 0xef, 0xa0, 0xeb, 0x91, 0x4b, 0x23, 0x2b, 0x64, 0xcf, 0x57, 0xb6, 0xf3, 0xac, 0x0f, 0xfa, 0xb5, + 0xeb, 0x07, 0xa2, 0x08, 0xe7, 0xb1, 0xca, 0x4f, 0x8b, 0xb9, 0xfc, 0xf2, 0x3e, 0xf8, 0x00, 0xad, + 0x65, 0xda, 0x01, 0xa5, 0xfb, 0x23, 0x1b, 0x6e, 0xc6, 0x36, 0x64, 0xb5, 0x86, 0x00, 0x3c, 0xae, + 0x23, 0x7f, 0x8d, 0x56, 0xfc, 0x6c, 0xa8, 0xe3, 0xd2, 0xbe, 0x37, 0x47, 0x4a, 0x27, 0xa4, 0x4a, + 0x5f, 0x1b, 0xf4, 0x6b, 0x2b, 0x82, 0x00, 0x8b, 0xe7, 0xc8, 0x4d, 0x54, 0x26, 0xe9, 0xc0, 0xf2, + 0x90, 0xf5, 0xf2, 0x61, 0x1a, 0x1a, 0x49, 0xfb, 0xdb, 0x11, 0xa4, 0xcf, 0xc7, 0x76, 0x70, 0x4e, + 0x5f, 0xf9, 0x6b, 0x11, 0xad, 0x4f, 0x68, 0x0f, 0xf2, 0x36, 0x42, 0x66, 0x60, 0xf5, 0x20, 0xc8, + 0x04, 0x29, 0x6d, 0x73, 0xbb, 0xa9, 0x04, 0x67, 0x50, 0xf2, 0xe7, 0x08, 0x8d, 0xd8, 0xe3, 0x98, + 0xa8, 0xb3, 0x63, 0x92, 0x1f, 0xbf, 0xf4, 0x32, 0xe3, 0xcf, 0xec, 0x66, 0x18, 0x65, 0x8a, 0x4a, + 0x01, 0x50, 0x08, 0x7a, 0x60, 0xbe, 0xe7, 0x05, 0x95, 0x02, 0xaf, 0xa3, 0xb7, 0xe7, 0x08, 0xfa, + 0x58, 0x2b, 0xd3, 0xd7, 0x63, 0x97, 0x4a, 0x78, 0x44, 0x8c, 0xb3, 0xa7, 0xc8, 0x2d, 0xb4, 0x61, + 0x02, 0xc9, 0x98, 0xf9, 0x55, 0x04, 0x34, 0x04, 0x93, 0x77, 0xa8, 0x25, 0xfd, 0x76, 0x4c, 0xb0, + 0xb1, 0x3b, 0x09, 0x84, 0x27, 0xeb, 0x2a, 0xbf, 0x49, 0x68, 0x43, 0xb0, 0xec, 0x63, 0x70, 0x7c, + 0x9b, 0x84, 0x70, 0x01, 0xcf, 0xd1, 0xa1, 0xf0, 0x1c, 0xbd, 0x31, 0x47, 0xf8, 0x12, 0x23, 0xa7, + 0x3d, 0x4b, 0xca, 0xaf, 0x12, 0xba, 0x39, 0x51, 0xe3, 0x02, 0xda, 0xeb, 0x27, 0x62, 0x7b, 0x7d, + 0xf5, 0x1c, 0x7e, 0x4d, 0x69, 0xb3, 0x27, 0xd3, 0xbc, 0xe2, 0x4d, 0xe5, 0xff, 0x38, 0x3f, 0x28, + 0x7f, 0x8b, 0x63, 0x10, 0xa5, 0x17, 0xe0, 0x86, 0xd8, 0x51, 0x16, 0xcf, 0xd4, 0x51, 0xc6, 0x1a, + 0x6d, 0x61, 0xce, 0x46, 0x4b, 0xe9, 0xf9, 0x1a, 0xed, 0x21, 0x5a, 0x11, 0x5f, 0x9f, 0xe2, 0x19, + 0x3f, 0xe1, 0x38, 0x75, 0x4b, 0x78, 0x9d, 0x44, 0xa6, 0xfc, 0xec, 0x41, 0xe9, 0x65, 0x9e, 0x3d, + 0x28, 0x9d, 0x52, 0x14, 0xbf, 0x88, 0xb3, 0xc7, 0xc4, 0x38, 0x5f, 0xfc, 0xec, 0xc1, 0xbe, 0x8c, + 0xd9, 0x5f, 0xea, 0x13, 0x23, 0x99, 0x21, 0xd3, 0x2f, 0xe3, 0xfd, 0x44, 0x80, 0x47, 0x18, 0x5d, + 0x3f, 0x3e, 0xad, 0x2e, 0x9c, 0x9c, 0x56, 0x17, 0x9e, 0x9d, 0x56, 0x17, 0x9e, 0x0e, 0xaa, 0xd2, + 0xf1, 0xa0, 0x2a, 0x9d, 0x0c, 0xaa, 0xd2, 0xb3, 0x41, 0x55, 0xfa, 0x7d, 0x50, 0x95, 0xbe, 0xfb, + 0xa3, 0xba, 0xf0, 0xe9, 0xad, 0x59, 0xbf, 0xb3, 0xfc, 0x13, 0x00, 0x00, 0xff, 0xff, 0xe7, 0x0a, + 0x8b, 0x49, 0x9f, 0x11, 0x00, 0x00, +} + +func (m *AllocationResult) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AllocationResult) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AllocationResult) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i-- + if m.Shareable { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + if m.AvailableOnNodes != nil { + { + size, err := m.AvailableOnNodes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + i -= len(m.ResourceHandle) + copy(dAtA[i:], m.ResourceHandle) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ResourceHandle))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *PodScheduling) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodScheduling) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodScheduling) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Status.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size, err := m.Spec.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.ObjectMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *PodSchedulingList) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSchedulingList) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSchedulingList) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Items) > 0 { + for iNdEx := len(m.Items) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Items[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.ListMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *PodSchedulingSpec) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSchedulingSpec) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSchedulingSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.PotentialNodes) > 0 { + for iNdEx := len(m.PotentialNodes) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.PotentialNodes[iNdEx]) + copy(dAtA[i:], m.PotentialNodes[iNdEx]) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.PotentialNodes[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + i -= len(m.SelectedNode) + copy(dAtA[i:], m.SelectedNode) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.SelectedNode))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *PodSchedulingStatus) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PodSchedulingStatus) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PodSchedulingStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ResourceClaims) > 0 { + for iNdEx := len(m.ResourceClaims) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ResourceClaims[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ResourceClaim) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClaim) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClaim) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Status.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size, err := m.Spec.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.ObjectMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ResourceClaimConsumerReference) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClaimConsumerReference) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClaimConsumerReference) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i -= len(m.UID) + copy(dAtA[i:], m.UID) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.UID))) + i-- + dAtA[i] = 0x2a + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x22 + i -= len(m.Resource) + copy(dAtA[i:], m.Resource) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Resource))) + i-- + dAtA[i] = 0x1a + i -= len(m.APIGroup) + copy(dAtA[i:], m.APIGroup) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.APIGroup))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ResourceClaimList) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClaimList) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClaimList) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Items) > 0 { + for iNdEx := len(m.Items) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Items[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.ListMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ResourceClaimParametersReference) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClaimParametersReference) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClaimParametersReference) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x1a + i -= len(m.Kind) + copy(dAtA[i:], m.Kind) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Kind))) + i-- + dAtA[i] = 0x12 + i -= len(m.APIGroup) + copy(dAtA[i:], m.APIGroup) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.APIGroup))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ResourceClaimSchedulingStatus) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClaimSchedulingStatus) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClaimSchedulingStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.UnsuitableNodes) > 0 { + for iNdEx := len(m.UnsuitableNodes) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.UnsuitableNodes[iNdEx]) + copy(dAtA[i:], m.UnsuitableNodes[iNdEx]) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.UnsuitableNodes[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ResourceClaimSpec) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClaimSpec) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClaimSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i -= len(m.AllocationMode) + copy(dAtA[i:], m.AllocationMode) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.AllocationMode))) + i-- + dAtA[i] = 0x1a + if m.ParametersRef != nil { + { + size, err := m.ParametersRef.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + i -= len(m.ResourceClassName) + copy(dAtA[i:], m.ResourceClassName) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ResourceClassName))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ResourceClaimStatus) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClaimStatus) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClaimStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i-- + if m.DeallocationRequested { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + if len(m.ReservedFor) > 0 { + for iNdEx := len(m.ReservedFor) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ReservedFor[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.Allocation != nil { + { + size, err := m.Allocation.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + i -= len(m.DriverName) + copy(dAtA[i:], m.DriverName) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.DriverName))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ResourceClaimTemplate) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClaimTemplate) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClaimTemplate) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Spec.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.ObjectMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ResourceClaimTemplateList) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClaimTemplateList) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClaimTemplateList) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Items) > 0 { + for iNdEx := len(m.Items) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Items[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.ListMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ResourceClaimTemplateSpec) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClaimTemplateSpec) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClaimTemplateSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Spec.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.ObjectMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ResourceClass) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClass) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClass) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.SuitableNodes != nil { + { + size, err := m.SuitableNodes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.ParametersRef != nil { + { + size, err := m.ParametersRef.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + i -= len(m.DriverName) + copy(dAtA[i:], m.DriverName) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.DriverName))) + i-- + dAtA[i] = 0x12 + { + size, err := m.ObjectMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ResourceClassList) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClassList) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClassList) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Items) > 0 { + for iNdEx := len(m.Items) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Items[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.ListMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ResourceClassParametersReference) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResourceClassParametersReference) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResourceClassParametersReference) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i -= len(m.Namespace) + copy(dAtA[i:], m.Namespace) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Namespace))) + i-- + dAtA[i] = 0x22 + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x1a + i -= len(m.Kind) + copy(dAtA[i:], m.Kind) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Kind))) + i-- + dAtA[i] = 0x12 + i -= len(m.APIGroup) + copy(dAtA[i:], m.APIGroup) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.APIGroup))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { + offset -= sovGenerated(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *AllocationResult) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ResourceHandle) + n += 1 + l + sovGenerated(uint64(l)) + if m.AvailableOnNodes != nil { + l = m.AvailableOnNodes.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + n += 2 + return n +} + +func (m *PodScheduling) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Spec.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Status.Size() + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *PodSchedulingList) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ListMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Items) > 0 { + for _, e := range m.Items { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *PodSchedulingSpec) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.SelectedNode) + n += 1 + l + sovGenerated(uint64(l)) + if len(m.PotentialNodes) > 0 { + for _, s := range m.PotentialNodes { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *PodSchedulingStatus) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ResourceClaims) > 0 { + for _, e := range m.ResourceClaims { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *ResourceClaim) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Spec.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Status.Size() + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *ResourceClaimConsumerReference) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.APIGroup) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Resource) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.UID) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *ResourceClaimList) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ListMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Items) > 0 { + for _, e := range m.Items { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *ResourceClaimParametersReference) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.APIGroup) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Kind) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *ResourceClaimSchedulingStatus) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + if len(m.UnsuitableNodes) > 0 { + for _, s := range m.UnsuitableNodes { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *ResourceClaimSpec) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ResourceClassName) + n += 1 + l + sovGenerated(uint64(l)) + if m.ParametersRef != nil { + l = m.ParametersRef.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + l = len(m.AllocationMode) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *ResourceClaimStatus) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.DriverName) + n += 1 + l + sovGenerated(uint64(l)) + if m.Allocation != nil { + l = m.Allocation.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if len(m.ReservedFor) > 0 { + for _, e := range m.ReservedFor { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + n += 2 + return n +} + +func (m *ResourceClaimTemplate) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Spec.Size() + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *ResourceClaimTemplateList) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ListMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Items) > 0 { + for _, e := range m.Items { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *ResourceClaimTemplateSpec) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Spec.Size() + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *ResourceClass) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.DriverName) + n += 1 + l + sovGenerated(uint64(l)) + if m.ParametersRef != nil { + l = m.ParametersRef.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.SuitableNodes != nil { + l = m.SuitableNodes.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + +func (m *ResourceClassList) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ListMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Items) > 0 { + for _, e := range m.Items { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *ResourceClassParametersReference) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.APIGroup) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Kind) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Namespace) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func sovGenerated(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenerated(x uint64) (n int) { + return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *AllocationResult) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&AllocationResult{`, + `ResourceHandle:` + fmt.Sprintf("%v", this.ResourceHandle) + `,`, + `AvailableOnNodes:` + strings.Replace(fmt.Sprintf("%v", this.AvailableOnNodes), "NodeSelector", "v1.NodeSelector", 1) + `,`, + `Shareable:` + fmt.Sprintf("%v", this.Shareable) + `,`, + `}`, + }, "") + return s +} +func (this *PodScheduling) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PodScheduling{`, + `ObjectMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ObjectMeta), "ObjectMeta", "v11.ObjectMeta", 1), `&`, ``, 1) + `,`, + `Spec:` + strings.Replace(strings.Replace(this.Spec.String(), "PodSchedulingSpec", "PodSchedulingSpec", 1), `&`, ``, 1) + `,`, + `Status:` + strings.Replace(strings.Replace(this.Status.String(), "PodSchedulingStatus", "PodSchedulingStatus", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *PodSchedulingList) String() string { + if this == nil { + return "nil" + } + repeatedStringForItems := "[]PodScheduling{" + for _, f := range this.Items { + repeatedStringForItems += strings.Replace(strings.Replace(f.String(), "PodScheduling", "PodScheduling", 1), `&`, ``, 1) + "," + } + repeatedStringForItems += "}" + s := strings.Join([]string{`&PodSchedulingList{`, + `ListMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ListMeta), "ListMeta", "v11.ListMeta", 1), `&`, ``, 1) + `,`, + `Items:` + repeatedStringForItems + `,`, + `}`, + }, "") + return s +} +func (this *PodSchedulingSpec) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PodSchedulingSpec{`, + `SelectedNode:` + fmt.Sprintf("%v", this.SelectedNode) + `,`, + `PotentialNodes:` + fmt.Sprintf("%v", this.PotentialNodes) + `,`, + `}`, + }, "") + return s +} +func (this *PodSchedulingStatus) String() string { + if this == nil { + return "nil" + } + repeatedStringForResourceClaims := "[]ResourceClaimSchedulingStatus{" + for _, f := range this.ResourceClaims { + repeatedStringForResourceClaims += strings.Replace(strings.Replace(f.String(), "ResourceClaimSchedulingStatus", "ResourceClaimSchedulingStatus", 1), `&`, ``, 1) + "," + } + repeatedStringForResourceClaims += "}" + s := strings.Join([]string{`&PodSchedulingStatus{`, + `ResourceClaims:` + repeatedStringForResourceClaims + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClaim) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ResourceClaim{`, + `ObjectMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ObjectMeta), "ObjectMeta", "v11.ObjectMeta", 1), `&`, ``, 1) + `,`, + `Spec:` + strings.Replace(strings.Replace(this.Spec.String(), "ResourceClaimSpec", "ResourceClaimSpec", 1), `&`, ``, 1) + `,`, + `Status:` + strings.Replace(strings.Replace(this.Status.String(), "ResourceClaimStatus", "ResourceClaimStatus", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClaimConsumerReference) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ResourceClaimConsumerReference{`, + `APIGroup:` + fmt.Sprintf("%v", this.APIGroup) + `,`, + `Resource:` + fmt.Sprintf("%v", this.Resource) + `,`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `UID:` + fmt.Sprintf("%v", this.UID) + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClaimList) String() string { + if this == nil { + return "nil" + } + repeatedStringForItems := "[]ResourceClaim{" + for _, f := range this.Items { + repeatedStringForItems += strings.Replace(strings.Replace(f.String(), "ResourceClaim", "ResourceClaim", 1), `&`, ``, 1) + "," + } + repeatedStringForItems += "}" + s := strings.Join([]string{`&ResourceClaimList{`, + `ListMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ListMeta), "ListMeta", "v11.ListMeta", 1), `&`, ``, 1) + `,`, + `Items:` + repeatedStringForItems + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClaimParametersReference) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ResourceClaimParametersReference{`, + `APIGroup:` + fmt.Sprintf("%v", this.APIGroup) + `,`, + `Kind:` + fmt.Sprintf("%v", this.Kind) + `,`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClaimSchedulingStatus) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ResourceClaimSchedulingStatus{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `UnsuitableNodes:` + fmt.Sprintf("%v", this.UnsuitableNodes) + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClaimSpec) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ResourceClaimSpec{`, + `ResourceClassName:` + fmt.Sprintf("%v", this.ResourceClassName) + `,`, + `ParametersRef:` + strings.Replace(this.ParametersRef.String(), "ResourceClaimParametersReference", "ResourceClaimParametersReference", 1) + `,`, + `AllocationMode:` + fmt.Sprintf("%v", this.AllocationMode) + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClaimStatus) String() string { + if this == nil { + return "nil" + } + repeatedStringForReservedFor := "[]ResourceClaimConsumerReference{" + for _, f := range this.ReservedFor { + repeatedStringForReservedFor += strings.Replace(strings.Replace(f.String(), "ResourceClaimConsumerReference", "ResourceClaimConsumerReference", 1), `&`, ``, 1) + "," + } + repeatedStringForReservedFor += "}" + s := strings.Join([]string{`&ResourceClaimStatus{`, + `DriverName:` + fmt.Sprintf("%v", this.DriverName) + `,`, + `Allocation:` + strings.Replace(this.Allocation.String(), "AllocationResult", "AllocationResult", 1) + `,`, + `ReservedFor:` + repeatedStringForReservedFor + `,`, + `DeallocationRequested:` + fmt.Sprintf("%v", this.DeallocationRequested) + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClaimTemplate) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ResourceClaimTemplate{`, + `ObjectMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ObjectMeta), "ObjectMeta", "v11.ObjectMeta", 1), `&`, ``, 1) + `,`, + `Spec:` + strings.Replace(strings.Replace(this.Spec.String(), "ResourceClaimTemplateSpec", "ResourceClaimTemplateSpec", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClaimTemplateList) String() string { + if this == nil { + return "nil" + } + repeatedStringForItems := "[]ResourceClaimTemplate{" + for _, f := range this.Items { + repeatedStringForItems += strings.Replace(strings.Replace(f.String(), "ResourceClaimTemplate", "ResourceClaimTemplate", 1), `&`, ``, 1) + "," + } + repeatedStringForItems += "}" + s := strings.Join([]string{`&ResourceClaimTemplateList{`, + `ListMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ListMeta), "ListMeta", "v11.ListMeta", 1), `&`, ``, 1) + `,`, + `Items:` + repeatedStringForItems + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClaimTemplateSpec) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ResourceClaimTemplateSpec{`, + `ObjectMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ObjectMeta), "ObjectMeta", "v11.ObjectMeta", 1), `&`, ``, 1) + `,`, + `Spec:` + strings.Replace(strings.Replace(this.Spec.String(), "ResourceClaimSpec", "ResourceClaimSpec", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClass) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ResourceClass{`, + `ObjectMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ObjectMeta), "ObjectMeta", "v11.ObjectMeta", 1), `&`, ``, 1) + `,`, + `DriverName:` + fmt.Sprintf("%v", this.DriverName) + `,`, + `ParametersRef:` + strings.Replace(this.ParametersRef.String(), "ResourceClassParametersReference", "ResourceClassParametersReference", 1) + `,`, + `SuitableNodes:` + strings.Replace(fmt.Sprintf("%v", this.SuitableNodes), "NodeSelector", "v1.NodeSelector", 1) + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClassList) String() string { + if this == nil { + return "nil" + } + repeatedStringForItems := "[]ResourceClass{" + for _, f := range this.Items { + repeatedStringForItems += strings.Replace(strings.Replace(f.String(), "ResourceClass", "ResourceClass", 1), `&`, ``, 1) + "," + } + repeatedStringForItems += "}" + s := strings.Join([]string{`&ResourceClassList{`, + `ListMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ListMeta), "ListMeta", "v11.ListMeta", 1), `&`, ``, 1) + `,`, + `Items:` + repeatedStringForItems + `,`, + `}`, + }, "") + return s +} +func (this *ResourceClassParametersReference) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ResourceClassParametersReference{`, + `APIGroup:` + fmt.Sprintf("%v", this.APIGroup) + `,`, + `Kind:` + fmt.Sprintf("%v", this.Kind) + `,`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`, + `}`, + }, "") + return s +} +func valueToStringGenerated(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *AllocationResult) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AllocationResult: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AllocationResult: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResourceHandle", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ResourceHandle = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AvailableOnNodes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AvailableOnNodes == nil { + m.AvailableOnNodes = &v1.NodeSelector{} + } + if err := m.AvailableOnNodes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Shareable", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Shareable = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PodScheduling) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodScheduling: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodScheduling: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Status.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PodSchedulingList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSchedulingList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSchedulingList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, PodScheduling{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PodSchedulingSpec) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSchedulingSpec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSchedulingSpec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SelectedNode", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SelectedNode = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PotentialNodes", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PotentialNodes = append(m.PotentialNodes, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PodSchedulingStatus) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PodSchedulingStatus: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PodSchedulingStatus: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResourceClaims", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ResourceClaims = append(m.ResourceClaims, ResourceClaimSchedulingStatus{}) + if err := m.ResourceClaims[len(m.ResourceClaims)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClaim) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClaim: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClaim: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Status.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClaimConsumerReference) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClaimConsumerReference: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClaimConsumerReference: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field APIGroup", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.APIGroup = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Resource", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Resource = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UID = k8s_io_apimachinery_pkg_types.UID(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClaimList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClaimList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClaimList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, ResourceClaim{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClaimParametersReference) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClaimParametersReference: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClaimParametersReference: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field APIGroup", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.APIGroup = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Kind", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Kind = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClaimSchedulingStatus) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClaimSchedulingStatus: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClaimSchedulingStatus: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UnsuitableNodes", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UnsuitableNodes = append(m.UnsuitableNodes, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClaimSpec) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClaimSpec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClaimSpec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResourceClassName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ResourceClassName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ParametersRef", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ParametersRef == nil { + m.ParametersRef = &ResourceClaimParametersReference{} + } + if err := m.ParametersRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllocationMode", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllocationMode = AllocationMode(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClaimStatus) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClaimStatus: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClaimStatus: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DriverName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DriverName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Allocation", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Allocation == nil { + m.Allocation = &AllocationResult{} + } + if err := m.Allocation.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ReservedFor", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ReservedFor = append(m.ReservedFor, ResourceClaimConsumerReference{}) + if err := m.ReservedFor[len(m.ReservedFor)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DeallocationRequested", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.DeallocationRequested = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClaimTemplate) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClaimTemplate: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClaimTemplate: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClaimTemplateList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClaimTemplateList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClaimTemplateList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, ResourceClaimTemplate{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClaimTemplateSpec) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClaimTemplateSpec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClaimTemplateSpec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClass) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClass: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClass: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DriverName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DriverName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ParametersRef", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ParametersRef == nil { + m.ParametersRef = &ResourceClassParametersReference{} + } + if err := m.ParametersRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SuitableNodes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SuitableNodes == nil { + m.SuitableNodes = &v1.NodeSelector{} + } + if err := m.SuitableNodes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClassList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClassList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClassList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, ResourceClass{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResourceClassParametersReference) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResourceClassParametersReference: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResourceClassParametersReference: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field APIGroup", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.APIGroup = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Kind", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Kind = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Namespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenerated(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenerated + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenerated + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenerated + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenerated = fmt.Errorf("proto: unexpected end of group") +) diff --git a/staging/src/k8s.io/api/resource/v1alpha1/generated.proto b/staging/src/k8s.io/api/resource/v1alpha1/generated.proto new file mode 100644 index 00000000000..5fc35e405ce --- /dev/null +++ b/staging/src/k8s.io/api/resource/v1alpha1/generated.proto @@ -0,0 +1,371 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +// This file was autogenerated by go-to-protobuf. Do not edit it manually! + +syntax = "proto2"; + +package k8s.io.api.resource.v1alpha1; + +import "k8s.io/api/core/v1/generated.proto"; +import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; +import "k8s.io/apimachinery/pkg/runtime/generated.proto"; +import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; + +// Package-wide variables from generator "generated". +option go_package = "k8s.io/api/resource/v1alpha1"; + +// AllocationResult contains attributed of an allocated resource. +message AllocationResult { + // ResourceHandle contains arbitrary data returned by the driver after a + // successful allocation. This is opaque for + // Kubernetes. Driver documentation may explain to users how to + // interpret this data if needed. + // + // The maximum size of this field is 16KiB. This may get + // increased in the future, but not reduced. + // +optional + optional string resourceHandle = 1; + + // This field will get set by the resource driver after it has + // allocated the resource driver to inform the scheduler where it can + // schedule Pods using the ResourceClaim. + // + // Setting this field is optional. If null, the resource is available + // everywhere. + // +optional + optional k8s.io.api.core.v1.NodeSelector availableOnNodes = 2; + + // Shareable determines whether the resource supports more + // than one consumer at a time. + // +optional + optional bool shareable = 3; +} + +// PodScheduling objects hold information that is needed to schedule +// a Pod with ResourceClaims that use "WaitForFirstConsumer" allocation +// mode. +// +// This is an alpha type and requires enabling the DynamicResourceAllocation +// feature gate. +message PodScheduling { + // Standard object metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // Spec describes where resources for the Pod are needed. + optional PodSchedulingSpec spec = 2; + + // Status describes where resources for the Pod can be allocated. + // +optional + optional PodSchedulingStatus status = 3; +} + +// PodSchedulingList is a collection of Pod scheduling objects. +message PodSchedulingList { + // Standard list metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; + + // Items is the list of PodScheduling objects. + repeated PodScheduling items = 2; +} + +// PodSchedulingSpec describes where resources for the Pod are needed. +message PodSchedulingSpec { + // SelectedNode is the node for which allocation of ResourceClaims that + // are referenced by the Pod and that use "WaitForFirstConsumer" + // allocation is to be attempted. + // +optional + optional string selectedNode = 1; + + // PotentialNodes lists nodes where the Pod might be able to run. + // + // The size of this field is limited to 128. This is large enough for + // many clusters. Larger clusters may need more attempts to find a node + // that suits all pending resources. This may get increased in the + // future, but not reduced. + // + // +listType=set + // +optional + repeated string potentialNodes = 2; +} + +// PodSchedulingStatus describes where resources for the Pod can be allocated. +message PodSchedulingStatus { + // ResourceClaims describes resource availability for each + // pod.spec.resourceClaim entry where the corresponding ResourceClaim + // uses "WaitForFirstConsumer" allocation mode. + // + // +listType=map + // +listMapKey=name + // +optional + repeated ResourceClaimSchedulingStatus resourceClaims = 1; +} + +// ResourceClaim describes which resources are needed by a resource consumer. +// Its status tracks whether the resource has been allocated and what the +// resulting attributes are. +// +// This is an alpha type and requires enabling the DynamicResourceAllocation +// feature gate. +message ResourceClaim { + // Standard object metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // Spec describes the desired attributes of a resource that then needs + // to be allocated. It can only be set once when creating the + // ResourceClaim. + optional ResourceClaimSpec spec = 2; + + // Status describes whether the resource is available and with which + // attributes. + // +optional + optional ResourceClaimStatus status = 3; +} + +// ResourceClaimConsumerReference contains enough information to let you +// locate the consumer of a ResourceClaim. The user must be a resource in the same +// namespace as the ResourceClaim. +message ResourceClaimConsumerReference { + // APIGroup is the group for the resource being referenced. It is + // empty for the core API. This matches the group in the APIVersion + // that is used when creating the resources. + // +optional + optional string apiGroup = 1; + + // Resource is the type of resource being referenced, for example "pods". + optional string resource = 3; + + // Name is the name of resource being referenced. + optional string name = 4; + + // UID identifies exactly one incarnation of the resource. + optional string uid = 5; +} + +// ResourceClaimList is a collection of claims. +message ResourceClaimList { + // Standard list metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; + + // Items is the list of resource claims. + repeated ResourceClaim items = 2; +} + +// ResourceClaimParametersReference contains enough information to let you +// locate the parameters for a ResourceClaim. The object must be in the same +// namespace as the ResourceClaim. +message ResourceClaimParametersReference { + // APIGroup is the group for the resource being referenced. It is + // empty for the core API. This matches the group in the APIVersion + // that is used when creating the resources. + // +optional + optional string apiGroup = 1; + + // Kind is the type of resource being referenced. This is the same + // value as in the parameter object's metadata, for example "ConfigMap". + optional string kind = 2; + + // Name is the name of resource being referenced. + optional string name = 3; +} + +// ResourceClaimSchedulingStatus contains information about one particular +// ResourceClaim with "WaitForFirstConsumer" allocation mode. +message ResourceClaimSchedulingStatus { + // Name matches the pod.spec.resourceClaims[*].Name field. + // +optional + optional string name = 1; + + // UnsuitableNodes lists nodes that the ResourceClaim cannot be + // allocated for. + // + // The size of this field is limited to 128, the same as for + // PodSchedulingSpec.PotentialNodes. This may get increased in the + // future, but not reduced. + // + // +listType=set + // +optional + repeated string unsuitableNodes = 2; +} + +// ResourceClaimSpec defines how a resource is to be allocated. +message ResourceClaimSpec { + // ResourceClassName references the driver and additional parameters + // via the name of a ResourceClass that was created as part of the + // driver deployment. + optional string resourceClassName = 1; + + // ParametersRef references a separate object with arbitrary parameters + // that will be used by the driver when allocating a resource for the + // claim. + // + // The object must be in the same namespace as the ResourceClaim. + // +optional + optional ResourceClaimParametersReference parametersRef = 2; + + // Allocation can start immediately or when a Pod wants to use the + // resource. "WaitForFirstConsumer" is the default. + // +optional + optional string allocationMode = 3; +} + +// ResourceClaimStatus tracks whether the resource has been allocated and what +// the resulting attributes are. +message ResourceClaimStatus { + // DriverName is a copy of the driver name from the ResourceClass at + // the time when allocation started. + // +optional + optional string driverName = 1; + + // Allocation is set by the resource driver once a resource has been + // allocated successfully. If this is not specified, the resource is + // not yet allocated. + // +optional + optional AllocationResult allocation = 2; + + // ReservedFor indicates which entities are currently allowed to use + // the claim. A Pod which references a ResourceClaim which is not + // reserved for that Pod will not be started. + // + // There can be at most 32 such reservations. This may get increased in + // the future, but not reduced. + // + // +listType=set + // +optional + repeated ResourceClaimConsumerReference reservedFor = 3; + + // DeallocationRequested indicates that a ResourceClaim is to be + // deallocated. + // + // The driver then must deallocate this claim and reset the field + // together with clearing the Allocation field. + // + // While DeallocationRequested is set, no new consumers may be added to + // ReservedFor. + // +optional + optional bool deallocationRequested = 4; +} + +// ResourceClaimTemplate is used to produce ResourceClaim objects. +message ResourceClaimTemplate { + // Standard object metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // Describes the ResourceClaim that is to be generated. + // + // This field is immutable. A ResourceClaim will get created by the + // control plane for a Pod when needed and then not get updated + // anymore. + optional ResourceClaimTemplateSpec spec = 2; +} + +// ResourceClaimTemplateList is a collection of claim templates. +message ResourceClaimTemplateList { + // Standard list metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; + + // Items is the list of resource claim templates. + repeated ResourceClaimTemplate items = 2; +} + +// ResourceClaimTemplateSpec contains the metadata and fields for a ResourceClaim. +message ResourceClaimTemplateSpec { + // ObjectMeta may contain labels and annotations that will be copied into the PVC + // when creating it. No other fields are allowed and will be rejected during + // validation. + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // Spec for the ResourceClaim. The entire content is copied unchanged + // into the ResourceClaim that gets created from this template. The + // same fields as in a ResourceClaim are also valid here. + optional ResourceClaimSpec spec = 2; +} + +// ResourceClass is used by administrators to influence how resources +// are allocated. +// +// This is an alpha type and requires enabling the DynamicResourceAllocation +// feature gate. +message ResourceClass { + // Standard object metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // DriverName defines the name of the dynamic resource driver that is + // used for allocation of a ResourceClaim that uses this class. + // + // Resource drivers have a unique name in forward domain order + // (acme.example.com). + optional string driverName = 2; + + // ParametersRef references an arbitrary separate object that may hold + // parameters that will be used by the driver when allocating a + // resource that uses this class. A dynamic resource driver can + // distinguish between parameters stored here and and those stored in + // ResourceClaimSpec. + // +optional + optional ResourceClassParametersReference parametersRef = 3; + + // Only nodes matching the selector will be considered by the scheduler + // when trying to find a Node that fits a Pod when that Pod uses + // a ResourceClaim that has not been allocated yet. + // + // Setting this field is optional. If null, all nodes are candidates. + // +optional + optional k8s.io.api.core.v1.NodeSelector suitableNodes = 4; +} + +// ResourceClassList is a collection of classes. +message ResourceClassList { + // Standard list metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; + + // Items is the list of resource classes. + repeated ResourceClass items = 2; +} + +// ResourceClassParametersReference contains enough information to let you +// locate the parameters for a ResourceClass. +message ResourceClassParametersReference { + // APIGroup is the group for the resource being referenced. It is + // empty for the core API. This matches the group in the APIVersion + // that is used when creating the resources. + // +optional + optional string apiGroup = 1; + + // Kind is the type of resource being referenced. This is the same + // value as in the parameter object's metadata. + optional string kind = 2; + + // Name is the name of resource being referenced. + optional string name = 3; + + // Namespace that contains the referenced resource. Must be empty + // for cluster-scoped resources and non-empty for namespaced + // resources. + // +optional + optional string namespace = 4; +} + diff --git a/staging/src/k8s.io/api/resource/v1alpha1/register.go b/staging/src/k8s.io/api/resource/v1alpha1/register.go new file mode 100644 index 00000000000..8245b9aee5d --- /dev/null +++ b/staging/src/k8s.io/api/resource/v1alpha1/register.go @@ -0,0 +1,63 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "resource.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to the given scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ResourceClass{}, + &ResourceClassList{}, + &ResourceClaim{}, + &ResourceClaimList{}, + &ResourceClaimTemplate{}, + &ResourceClaimTemplateList{}, + &PodScheduling{}, + &PodSchedulingList{}, + ) + + // Add common types + scheme.AddKnownTypes(SchemeGroupVersion, &metav1.Status{}) + + // Add the watch version that applies + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/staging/src/k8s.io/api/resource/v1alpha1/types.go b/staging/src/k8s.io/api/resource/v1alpha1/types.go new file mode 100644 index 00000000000..9d7d4a191af --- /dev/null +++ b/staging/src/k8s.io/api/resource/v1alpha1/types.go @@ -0,0 +1,429 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:prerelease-lifecycle-gen:introduced=1.26 + +// ResourceClaim describes which resources are needed by a resource consumer. +// Its status tracks whether the resource has been allocated and what the +// resulting attributes are. +// +// This is an alpha type and requires enabling the DynamicResourceAllocation +// feature gate. +type ResourceClaim struct { + metav1.TypeMeta `json:",inline"` + // Standard object metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Spec describes the desired attributes of a resource that then needs + // to be allocated. It can only be set once when creating the + // ResourceClaim. + Spec ResourceClaimSpec `json:"spec" protobuf:"bytes,2,name=spec"` + + // Status describes whether the resource is available and with which + // attributes. + // +optional + Status ResourceClaimStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` +} + +// ResourceClaimSpec defines how a resource is to be allocated. +type ResourceClaimSpec struct { + // ResourceClassName references the driver and additional parameters + // via the name of a ResourceClass that was created as part of the + // driver deployment. + ResourceClassName string `json:"resourceClassName" protobuf:"bytes,1,name=resourceClassName"` + + // ParametersRef references a separate object with arbitrary parameters + // that will be used by the driver when allocating a resource for the + // claim. + // + // The object must be in the same namespace as the ResourceClaim. + // +optional + ParametersRef *ResourceClaimParametersReference `json:"parametersRef,omitempty" protobuf:"bytes,2,opt,name=parametersRef"` + + // Allocation can start immediately or when a Pod wants to use the + // resource. "WaitForFirstConsumer" is the default. + // +optional + AllocationMode AllocationMode `json:"allocationMode,omitempty" protobuf:"bytes,3,opt,name=allocationMode"` +} + +// AllocationMode describes whether a ResourceClaim gets allocated immediately +// when it gets created (AllocationModeImmediate) or whether allocation is +// delayed until it is needed for a Pod +// (AllocationModeWaitForFirstConsumer). Other modes might get added in the +// future. +type AllocationMode string + +const ( + // When a ResourceClaim has AllocationModeWaitForFirstConsumer, allocation is + // delayed until a Pod gets scheduled that needs the ResourceClaim. The + // scheduler will consider all resource requirements of that Pod and + // trigger allocation for a node that fits the Pod. + AllocationModeWaitForFirstConsumer AllocationMode = "WaitForFirstConsumer" + + // When a ResourceClaim has AllocationModeImmediate, allocation starts + // as soon as the ResourceClaim gets created. This is done without + // considering the needs of Pods that will use the ResourceClaim + // because those Pods are not known yet. + AllocationModeImmediate AllocationMode = "Immediate" +) + +// ResourceClaimStatus tracks whether the resource has been allocated and what +// the resulting attributes are. +type ResourceClaimStatus struct { + // DriverName is a copy of the driver name from the ResourceClass at + // the time when allocation started. + // +optional + DriverName string `json:"driverName,omitempty" protobuf:"bytes,1,opt,name=driverName"` + + // Allocation is set by the resource driver once a resource has been + // allocated successfully. If this is not specified, the resource is + // not yet allocated. + // +optional + Allocation *AllocationResult `json:"allocation,omitempty" protobuf:"bytes,2,opt,name=allocation"` + + // ReservedFor indicates which entities are currently allowed to use + // the claim. A Pod which references a ResourceClaim which is not + // reserved for that Pod will not be started. + // + // There can be at most 32 such reservations. This may get increased in + // the future, but not reduced. + // + // +listType=set + // +optional + ReservedFor []ResourceClaimConsumerReference `json:"reservedFor,omitempty" protobuf:"bytes,3,opt,name=reservedFor"` + + // DeallocationRequested indicates that a ResourceClaim is to be + // deallocated. + // + // The driver then must deallocate this claim and reset the field + // together with clearing the Allocation field. + // + // While DeallocationRequested is set, no new consumers may be added to + // ReservedFor. + // +optional + DeallocationRequested bool `json:"deallocationRequested,omitempty" protobuf:"varint,4,opt,name=deallocationRequested"` +} + +// ReservedForMaxSize is the maximum number of entries in +// claim.status.reservedFor. +const ResourceClaimReservedForMaxSize = 32 + +// AllocationResult contains attributed of an allocated resource. +type AllocationResult struct { + // ResourceHandle contains arbitrary data returned by the driver after a + // successful allocation. This is opaque for + // Kubernetes. Driver documentation may explain to users how to + // interpret this data if needed. + // + // The maximum size of this field is 16KiB. This may get + // increased in the future, but not reduced. + // +optional + ResourceHandle string `json:"resourceHandle,omitempty" protobuf:"bytes,1,opt,name=resourceHandle"` + + // This field will get set by the resource driver after it has + // allocated the resource driver to inform the scheduler where it can + // schedule Pods using the ResourceClaim. + // + // Setting this field is optional. If null, the resource is available + // everywhere. + // +optional + AvailableOnNodes *v1.NodeSelector `json:"availableOnNodes,omitempty" protobuf:"bytes,2,opt,name=availableOnNodes"` + + // Shareable determines whether the resource supports more + // than one consumer at a time. + // +optional + Shareable bool `json:"shareable,omitempty" protobuf:"varint,3,opt,name=shareable"` +} + +// ResourceHandleMaxSize is the maximum size of allocation.resourceHandle. +const ResourceHandleMaxSize = 16 * 1024 + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:prerelease-lifecycle-gen:introduced=1.26 + +// ResourceClaimList is a collection of claims. +type ResourceClaimList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Items is the list of resource claims. + Items []ResourceClaim `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:prerelease-lifecycle-gen:introduced=1.26 + +// PodScheduling objects hold information that is needed to schedule +// a Pod with ResourceClaims that use "WaitForFirstConsumer" allocation +// mode. +// +// This is an alpha type and requires enabling the DynamicResourceAllocation +// feature gate. +type PodScheduling struct { + metav1.TypeMeta `json:",inline"` + // Standard object metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Spec describes where resources for the Pod are needed. + Spec PodSchedulingSpec `json:"spec" protobuf:"bytes,2,name=spec"` + + // Status describes where resources for the Pod can be allocated. + // +optional + Status PodSchedulingStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` +} + +// PodSchedulingSpec describes where resources for the Pod are needed. +type PodSchedulingSpec struct { + // SelectedNode is the node for which allocation of ResourceClaims that + // are referenced by the Pod and that use "WaitForFirstConsumer" + // allocation is to be attempted. + // +optional + SelectedNode string `json:"selectedNode,omitempty" protobuf:"bytes,1,opt,name=selectedNode"` + + // PotentialNodes lists nodes where the Pod might be able to run. + // + // The size of this field is limited to 128. This is large enough for + // many clusters. Larger clusters may need more attempts to find a node + // that suits all pending resources. This may get increased in the + // future, but not reduced. + // + // +listType=set + // +optional + PotentialNodes []string `json:"potentialNodes,omitempty" protobuf:"bytes,2,opt,name=potentialNodes"` +} + +// PodSchedulingStatus describes where resources for the Pod can be allocated. +type PodSchedulingStatus struct { + // ResourceClaims describes resource availability for each + // pod.spec.resourceClaim entry where the corresponding ResourceClaim + // uses "WaitForFirstConsumer" allocation mode. + // + // +listType=map + // +listMapKey=name + // +optional + ResourceClaims []ResourceClaimSchedulingStatus `json:"resourceClaims,omitempty" protobuf:"bytes,1,opt,name=resourceClaims"` + + // If there ever is a need to support other kinds of resources + // than ResourceClaim, then new fields could get added here + // for those other resources. +} + +// ResourceClaimSchedulingStatus contains information about one particular +// ResourceClaim with "WaitForFirstConsumer" allocation mode. +type ResourceClaimSchedulingStatus struct { + // Name matches the pod.spec.resourceClaims[*].Name field. + // +optional + Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"` + + // UnsuitableNodes lists nodes that the ResourceClaim cannot be + // allocated for. + // + // The size of this field is limited to 128, the same as for + // PodSchedulingSpec.PotentialNodes. This may get increased in the + // future, but not reduced. + // + // +listType=set + // +optional + UnsuitableNodes []string `json:"unsuitableNodes,omitempty" protobuf:"bytes,2,opt,name=unsuitableNodes"` +} + +// PodSchedulingNodeListMaxSize defines the maximum number of entries in the +// node lists that are stored in PodScheduling objects. This limit is part +// of the API. +const PodSchedulingNodeListMaxSize = 128 + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:prerelease-lifecycle-gen:introduced=1.26 + +// PodSchedulingList is a collection of Pod scheduling objects. +type PodSchedulingList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Items is the list of PodScheduling objects. + Items []PodScheduling `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:prerelease-lifecycle-gen:introduced=1.26 + +// ResourceClass is used by administrators to influence how resources +// are allocated. +// +// This is an alpha type and requires enabling the DynamicResourceAllocation +// feature gate. +type ResourceClass struct { + metav1.TypeMeta `json:",inline"` + // Standard object metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // DriverName defines the name of the dynamic resource driver that is + // used for allocation of a ResourceClaim that uses this class. + // + // Resource drivers have a unique name in forward domain order + // (acme.example.com). + DriverName string `json:"driverName" protobuf:"bytes,2,name=driverName"` + + // ParametersRef references an arbitrary separate object that may hold + // parameters that will be used by the driver when allocating a + // resource that uses this class. A dynamic resource driver can + // distinguish between parameters stored here and and those stored in + // ResourceClaimSpec. + // +optional + ParametersRef *ResourceClassParametersReference `json:"parametersRef,omitempty" protobuf:"bytes,3,opt,name=parametersRef"` + + // Only nodes matching the selector will be considered by the scheduler + // when trying to find a Node that fits a Pod when that Pod uses + // a ResourceClaim that has not been allocated yet. + // + // Setting this field is optional. If null, all nodes are candidates. + // +optional + SuitableNodes *v1.NodeSelector `json:"suitableNodes,omitempty" protobuf:"bytes,4,opt,name=suitableNodes"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:prerelease-lifecycle-gen:introduced=1.26 + +// ResourceClassList is a collection of classes. +type ResourceClassList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Items is the list of resource classes. + Items []ResourceClass `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// ResourceClassParametersReference contains enough information to let you +// locate the parameters for a ResourceClass. +type ResourceClassParametersReference struct { + // APIGroup is the group for the resource being referenced. It is + // empty for the core API. This matches the group in the APIVersion + // that is used when creating the resources. + // +optional + APIGroup string `json:"apiGroup,omitempty" protobuf:"bytes,1,opt,name=apiGroup"` + // Kind is the type of resource being referenced. This is the same + // value as in the parameter object's metadata. + Kind string `json:"kind" protobuf:"bytes,2,name=kind"` + // Name is the name of resource being referenced. + Name string `json:"name" protobuf:"bytes,3,name=name"` + // Namespace that contains the referenced resource. Must be empty + // for cluster-scoped resources and non-empty for namespaced + // resources. + // +optional + Namespace string `json:"namespace,omitempty" protobuf:"bytes,4,opt,name=namespace"` +} + +// ResourceClaimParametersReference contains enough information to let you +// locate the parameters for a ResourceClaim. The object must be in the same +// namespace as the ResourceClaim. +type ResourceClaimParametersReference struct { + // APIGroup is the group for the resource being referenced. It is + // empty for the core API. This matches the group in the APIVersion + // that is used when creating the resources. + // +optional + APIGroup string `json:"apiGroup,omitempty" protobuf:"bytes,1,opt,name=apiGroup"` + // Kind is the type of resource being referenced. This is the same + // value as in the parameter object's metadata, for example "ConfigMap". + Kind string `json:"kind" protobuf:"bytes,2,name=kind"` + // Name is the name of resource being referenced. + Name string `json:"name" protobuf:"bytes,3,name=name"` +} + +// ResourceClaimConsumerReference contains enough information to let you +// locate the consumer of a ResourceClaim. The user must be a resource in the same +// namespace as the ResourceClaim. +type ResourceClaimConsumerReference struct { + // APIGroup is the group for the resource being referenced. It is + // empty for the core API. This matches the group in the APIVersion + // that is used when creating the resources. + // +optional + APIGroup string `json:"apiGroup,omitempty" protobuf:"bytes,1,opt,name=apiGroup"` + // Resource is the type of resource being referenced, for example "pods". + Resource string `json:"resource" protobuf:"bytes,3,name=resource"` + // Name is the name of resource being referenced. + Name string `json:"name" protobuf:"bytes,4,name=name"` + // UID identifies exactly one incarnation of the resource. + UID types.UID `json:"uid" protobuf:"bytes,5,name=uid"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:prerelease-lifecycle-gen:introduced=1.26 + +// ResourceClaimTemplate is used to produce ResourceClaim objects. +type ResourceClaimTemplate struct { + metav1.TypeMeta `json:",inline"` + // Standard object metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Describes the ResourceClaim that is to be generated. + // + // This field is immutable. A ResourceClaim will get created by the + // control plane for a Pod when needed and then not get updated + // anymore. + Spec ResourceClaimTemplateSpec `json:"spec" protobuf:"bytes,2,name=spec"` +} + +// ResourceClaimTemplateSpec contains the metadata and fields for a ResourceClaim. +type ResourceClaimTemplateSpec struct { + // ObjectMeta may contain labels and annotations that will be copied into the PVC + // when creating it. No other fields are allowed and will be rejected during + // validation. + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Spec for the ResourceClaim. The entire content is copied unchanged + // into the ResourceClaim that gets created from this template. The + // same fields as in a ResourceClaim are also valid here. + Spec ResourceClaimSpec `json:"spec" protobuf:"bytes,2,name=spec"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:prerelease-lifecycle-gen:introduced=1.26 + +// ResourceClaimTemplateList is a collection of claim templates. +type ResourceClaimTemplateList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Items is the list of resource claim templates. + Items []ResourceClaimTemplate `json:"items" protobuf:"bytes,2,rep,name=items"` +} diff --git a/staging/src/k8s.io/api/resource/v1alpha1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/resource/v1alpha1/types_swagger_doc_generated.go new file mode 100644 index 00000000000..6836dbfb6e6 --- /dev/null +++ b/staging/src/k8s.io/api/resource/v1alpha1/types_swagger_doc_generated.go @@ -0,0 +1,222 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +// This file contains a collection of methods that can be used from go-restful to +// generate Swagger API documentation for its models. Please read this PR for more +// information on the implementation: https://github.com/emicklei/go-restful/pull/215 +// +// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if +// they are on one line! For multiple line or blocks that you want to ignore use ---. +// Any context after a --- is ignored. +// +// Those methods can be generated by using hack/update-generated-swagger-docs.sh + +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. +var map_AllocationResult = map[string]string{ + "": "AllocationResult contains attributed of an allocated resource.", + "resourceHandle": "ResourceHandle contains arbitrary data returned by the driver after a successful allocation. This is opaque for Kubernetes. Driver documentation may explain to users how to interpret this data if needed.\n\nThe maximum size of this field is 16KiB. This may get increased in the future, but not reduced.", + "availableOnNodes": "This field will get set by the resource driver after it has allocated the resource driver to inform the scheduler where it can schedule Pods using the ResourceClaim.\n\nSetting this field is optional. If null, the resource is available everywhere.", + "shareable": "Shareable determines whether the resource supports more than one consumer at a time.", +} + +func (AllocationResult) SwaggerDoc() map[string]string { + return map_AllocationResult +} + +var map_PodScheduling = map[string]string{ + "": "PodScheduling objects hold information that is needed to schedule a Pod with ResourceClaims that use \"WaitForFirstConsumer\" allocation mode.\n\nThis is an alpha type and requires enabling the DynamicResourceAllocation feature gate.", + "metadata": "Standard object metadata", + "spec": "Spec describes where resources for the Pod are needed.", + "status": "Status describes where resources for the Pod can be allocated.", +} + +func (PodScheduling) SwaggerDoc() map[string]string { + return map_PodScheduling +} + +var map_PodSchedulingList = map[string]string{ + "": "PodSchedulingList is a collection of Pod scheduling objects.", + "metadata": "Standard list metadata", + "items": "Items is the list of PodScheduling objects.", +} + +func (PodSchedulingList) SwaggerDoc() map[string]string { + return map_PodSchedulingList +} + +var map_PodSchedulingSpec = map[string]string{ + "": "PodSchedulingSpec describes where resources for the Pod are needed.", + "selectedNode": "SelectedNode is the node for which allocation of ResourceClaims that are referenced by the Pod and that use \"WaitForFirstConsumer\" allocation is to be attempted.", + "potentialNodes": "PotentialNodes lists nodes where the Pod might be able to run.\n\nThe size of this field is limited to 128. This is large enough for many clusters. Larger clusters may need more attempts to find a node that suits all pending resources. This may get increased in the future, but not reduced.", +} + +func (PodSchedulingSpec) SwaggerDoc() map[string]string { + return map_PodSchedulingSpec +} + +var map_PodSchedulingStatus = map[string]string{ + "": "PodSchedulingStatus describes where resources for the Pod can be allocated.", + "resourceClaims": "ResourceClaims describes resource availability for each pod.spec.resourceClaim entry where the corresponding ResourceClaim uses \"WaitForFirstConsumer\" allocation mode.", +} + +func (PodSchedulingStatus) SwaggerDoc() map[string]string { + return map_PodSchedulingStatus +} + +var map_ResourceClaim = map[string]string{ + "": "ResourceClaim describes which resources are needed by a resource consumer. Its status tracks whether the resource has been allocated and what the resulting attributes are.\n\nThis is an alpha type and requires enabling the DynamicResourceAllocation feature gate.", + "metadata": "Standard object metadata", + "spec": "Spec describes the desired attributes of a resource that then needs to be allocated. It can only be set once when creating the ResourceClaim.", + "status": "Status describes whether the resource is available and with which attributes.", +} + +func (ResourceClaim) SwaggerDoc() map[string]string { + return map_ResourceClaim +} + +var map_ResourceClaimConsumerReference = map[string]string{ + "": "ResourceClaimConsumerReference contains enough information to let you locate the consumer of a ResourceClaim. The user must be a resource in the same namespace as the ResourceClaim.", + "apiGroup": "APIGroup is the group for the resource being referenced. It is empty for the core API. This matches the group in the APIVersion that is used when creating the resources.", + "resource": "Resource is the type of resource being referenced, for example \"pods\".", + "name": "Name is the name of resource being referenced.", + "uid": "UID identifies exactly one incarnation of the resource.", +} + +func (ResourceClaimConsumerReference) SwaggerDoc() map[string]string { + return map_ResourceClaimConsumerReference +} + +var map_ResourceClaimList = map[string]string{ + "": "ResourceClaimList is a collection of claims.", + "metadata": "Standard list metadata", + "items": "Items is the list of resource claims.", +} + +func (ResourceClaimList) SwaggerDoc() map[string]string { + return map_ResourceClaimList +} + +var map_ResourceClaimParametersReference = map[string]string{ + "": "ResourceClaimParametersReference contains enough information to let you locate the parameters for a ResourceClaim. The object must be in the same namespace as the ResourceClaim.", + "apiGroup": "APIGroup is the group for the resource being referenced. It is empty for the core API. This matches the group in the APIVersion that is used when creating the resources.", + "kind": "Kind is the type of resource being referenced. This is the same value as in the parameter object's metadata, for example \"ConfigMap\".", + "name": "Name is the name of resource being referenced.", +} + +func (ResourceClaimParametersReference) SwaggerDoc() map[string]string { + return map_ResourceClaimParametersReference +} + +var map_ResourceClaimSchedulingStatus = map[string]string{ + "": "ResourceClaimSchedulingStatus contains information about one particular ResourceClaim with \"WaitForFirstConsumer\" allocation mode.", + "name": "Name matches the pod.spec.resourceClaims[*].Name field.", + "unsuitableNodes": "UnsuitableNodes lists nodes that the ResourceClaim cannot be allocated for.\n\nThe size of this field is limited to 128, the same as for PodSchedulingSpec.PotentialNodes. This may get increased in the future, but not reduced.", +} + +func (ResourceClaimSchedulingStatus) SwaggerDoc() map[string]string { + return map_ResourceClaimSchedulingStatus +} + +var map_ResourceClaimSpec = map[string]string{ + "": "ResourceClaimSpec defines how a resource is to be allocated.", + "resourceClassName": "ResourceClassName references the driver and additional parameters via the name of a ResourceClass that was created as part of the driver deployment.", + "parametersRef": "ParametersRef references a separate object with arbitrary parameters that will be used by the driver when allocating a resource for the claim.\n\nThe object must be in the same namespace as the ResourceClaim.", + "allocationMode": "Allocation can start immediately or when a Pod wants to use the resource. \"WaitForFirstConsumer\" is the default.", +} + +func (ResourceClaimSpec) SwaggerDoc() map[string]string { + return map_ResourceClaimSpec +} + +var map_ResourceClaimStatus = map[string]string{ + "": "ResourceClaimStatus tracks whether the resource has been allocated and what the resulting attributes are.", + "driverName": "DriverName is a copy of the driver name from the ResourceClass at the time when allocation started.", + "allocation": "Allocation is set by the resource driver once a resource has been allocated successfully. If this is not specified, the resource is not yet allocated.", + "reservedFor": "ReservedFor indicates which entities are currently allowed to use the claim. A Pod which references a ResourceClaim which is not reserved for that Pod will not be started.\n\nThere can be at most 32 such reservations. This may get increased in the future, but not reduced.", + "deallocationRequested": "DeallocationRequested indicates that a ResourceClaim is to be deallocated.\n\nThe driver then must deallocate this claim and reset the field together with clearing the Allocation field.\n\nWhile DeallocationRequested is set, no new consumers may be added to ReservedFor.", +} + +func (ResourceClaimStatus) SwaggerDoc() map[string]string { + return map_ResourceClaimStatus +} + +var map_ResourceClaimTemplate = map[string]string{ + "": "ResourceClaimTemplate is used to produce ResourceClaim objects.", + "metadata": "Standard object metadata", + "spec": "Describes the ResourceClaim that is to be generated.\n\nThis field is immutable. A ResourceClaim will get created by the control plane for a Pod when needed and then not get updated anymore.", +} + +func (ResourceClaimTemplate) SwaggerDoc() map[string]string { + return map_ResourceClaimTemplate +} + +var map_ResourceClaimTemplateList = map[string]string{ + "": "ResourceClaimTemplateList is a collection of claim templates.", + "metadata": "Standard list metadata", + "items": "Items is the list of resource claim templates.", +} + +func (ResourceClaimTemplateList) SwaggerDoc() map[string]string { + return map_ResourceClaimTemplateList +} + +var map_ResourceClaimTemplateSpec = map[string]string{ + "": "ResourceClaimTemplateSpec contains the metadata and fields for a ResourceClaim.", + "metadata": "ObjectMeta may contain labels and annotations that will be copied into the PVC when creating it. No other fields are allowed and will be rejected during validation.", + "spec": "Spec for the ResourceClaim. The entire content is copied unchanged into the ResourceClaim that gets created from this template. The same fields as in a ResourceClaim are also valid here.", +} + +func (ResourceClaimTemplateSpec) SwaggerDoc() map[string]string { + return map_ResourceClaimTemplateSpec +} + +var map_ResourceClass = map[string]string{ + "": "ResourceClass is used by administrators to influence how resources are allocated.\n\nThis is an alpha type and requires enabling the DynamicResourceAllocation feature gate.", + "metadata": "Standard object metadata", + "driverName": "DriverName defines the name of the dynamic resource driver that is used for allocation of a ResourceClaim that uses this class.\n\nResource drivers have a unique name in forward domain order (acme.example.com).", + "parametersRef": "ParametersRef references an arbitrary separate object that may hold parameters that will be used by the driver when allocating a resource that uses this class. A dynamic resource driver can distinguish between parameters stored here and and those stored in ResourceClaimSpec.", + "suitableNodes": "Only nodes matching the selector will be considered by the scheduler when trying to find a Node that fits a Pod when that Pod uses a ResourceClaim that has not been allocated yet.\n\nSetting this field is optional. If null, all nodes are candidates.", +} + +func (ResourceClass) SwaggerDoc() map[string]string { + return map_ResourceClass +} + +var map_ResourceClassList = map[string]string{ + "": "ResourceClassList is a collection of classes.", + "metadata": "Standard list metadata", + "items": "Items is the list of resource classes.", +} + +func (ResourceClassList) SwaggerDoc() map[string]string { + return map_ResourceClassList +} + +var map_ResourceClassParametersReference = map[string]string{ + "": "ResourceClassParametersReference contains enough information to let you locate the parameters for a ResourceClass.", + "apiGroup": "APIGroup is the group for the resource being referenced. It is empty for the core API. This matches the group in the APIVersion that is used when creating the resources.", + "kind": "Kind is the type of resource being referenced. This is the same value as in the parameter object's metadata.", + "name": "Name is the name of resource being referenced.", + "namespace": "Namespace that contains the referenced resource. Must be empty for cluster-scoped resources and non-empty for namespaced resources.", +} + +func (ResourceClassParametersReference) SwaggerDoc() map[string]string { + return map_ResourceClassParametersReference +} + +// AUTO-GENERATED FUNCTIONS END HERE diff --git a/staging/src/k8s.io/api/resource/v1alpha1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/resource/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..c00fbfd1d4e --- /dev/null +++ b/staging/src/k8s.io/api/resource/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,477 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AllocationResult) DeepCopyInto(out *AllocationResult) { + *out = *in + if in.AvailableOnNodes != nil { + in, out := &in.AvailableOnNodes, &out.AvailableOnNodes + *out = new(v1.NodeSelector) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllocationResult. +func (in *AllocationResult) DeepCopy() *AllocationResult { + if in == nil { + return nil + } + out := new(AllocationResult) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodScheduling) DeepCopyInto(out *PodScheduling) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodScheduling. +func (in *PodScheduling) DeepCopy() *PodScheduling { + if in == nil { + return nil + } + out := new(PodScheduling) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PodScheduling) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodSchedulingList) DeepCopyInto(out *PodSchedulingList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]PodScheduling, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSchedulingList. +func (in *PodSchedulingList) DeepCopy() *PodSchedulingList { + if in == nil { + return nil + } + out := new(PodSchedulingList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PodSchedulingList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodSchedulingSpec) DeepCopyInto(out *PodSchedulingSpec) { + *out = *in + if in.PotentialNodes != nil { + in, out := &in.PotentialNodes, &out.PotentialNodes + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSchedulingSpec. +func (in *PodSchedulingSpec) DeepCopy() *PodSchedulingSpec { + if in == nil { + return nil + } + out := new(PodSchedulingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodSchedulingStatus) DeepCopyInto(out *PodSchedulingStatus) { + *out = *in + if in.ResourceClaims != nil { + in, out := &in.ResourceClaims, &out.ResourceClaims + *out = make([]ResourceClaimSchedulingStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSchedulingStatus. +func (in *PodSchedulingStatus) DeepCopy() *PodSchedulingStatus { + if in == nil { + return nil + } + out := new(PodSchedulingStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaim) DeepCopyInto(out *ResourceClaim) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaim. +func (in *ResourceClaim) DeepCopy() *ResourceClaim { + if in == nil { + return nil + } + out := new(ResourceClaim) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ResourceClaim) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimConsumerReference) DeepCopyInto(out *ResourceClaimConsumerReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimConsumerReference. +func (in *ResourceClaimConsumerReference) DeepCopy() *ResourceClaimConsumerReference { + if in == nil { + return nil + } + out := new(ResourceClaimConsumerReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimList) DeepCopyInto(out *ResourceClaimList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ResourceClaim, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimList. +func (in *ResourceClaimList) DeepCopy() *ResourceClaimList { + if in == nil { + return nil + } + out := new(ResourceClaimList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ResourceClaimList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimParametersReference) DeepCopyInto(out *ResourceClaimParametersReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimParametersReference. +func (in *ResourceClaimParametersReference) DeepCopy() *ResourceClaimParametersReference { + if in == nil { + return nil + } + out := new(ResourceClaimParametersReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimSchedulingStatus) DeepCopyInto(out *ResourceClaimSchedulingStatus) { + *out = *in + if in.UnsuitableNodes != nil { + in, out := &in.UnsuitableNodes, &out.UnsuitableNodes + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimSchedulingStatus. +func (in *ResourceClaimSchedulingStatus) DeepCopy() *ResourceClaimSchedulingStatus { + if in == nil { + return nil + } + out := new(ResourceClaimSchedulingStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimSpec) DeepCopyInto(out *ResourceClaimSpec) { + *out = *in + if in.ParametersRef != nil { + in, out := &in.ParametersRef, &out.ParametersRef + *out = new(ResourceClaimParametersReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimSpec. +func (in *ResourceClaimSpec) DeepCopy() *ResourceClaimSpec { + if in == nil { + return nil + } + out := new(ResourceClaimSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimStatus) DeepCopyInto(out *ResourceClaimStatus) { + *out = *in + if in.Allocation != nil { + in, out := &in.Allocation, &out.Allocation + *out = new(AllocationResult) + (*in).DeepCopyInto(*out) + } + if in.ReservedFor != nil { + in, out := &in.ReservedFor, &out.ReservedFor + *out = make([]ResourceClaimConsumerReference, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimStatus. +func (in *ResourceClaimStatus) DeepCopy() *ResourceClaimStatus { + if in == nil { + return nil + } + out := new(ResourceClaimStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimTemplate) DeepCopyInto(out *ResourceClaimTemplate) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimTemplate. +func (in *ResourceClaimTemplate) DeepCopy() *ResourceClaimTemplate { + if in == nil { + return nil + } + out := new(ResourceClaimTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ResourceClaimTemplate) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimTemplateList) DeepCopyInto(out *ResourceClaimTemplateList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ResourceClaimTemplate, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimTemplateList. +func (in *ResourceClaimTemplateList) DeepCopy() *ResourceClaimTemplateList { + if in == nil { + return nil + } + out := new(ResourceClaimTemplateList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ResourceClaimTemplateList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClaimTemplateSpec) DeepCopyInto(out *ResourceClaimTemplateSpec) { + *out = *in + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClaimTemplateSpec. +func (in *ResourceClaimTemplateSpec) DeepCopy() *ResourceClaimTemplateSpec { + if in == nil { + return nil + } + out := new(ResourceClaimTemplateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClass) DeepCopyInto(out *ResourceClass) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.ParametersRef != nil { + in, out := &in.ParametersRef, &out.ParametersRef + *out = new(ResourceClassParametersReference) + **out = **in + } + if in.SuitableNodes != nil { + in, out := &in.SuitableNodes, &out.SuitableNodes + *out = new(v1.NodeSelector) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClass. +func (in *ResourceClass) DeepCopy() *ResourceClass { + if in == nil { + return nil + } + out := new(ResourceClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ResourceClass) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClassList) DeepCopyInto(out *ResourceClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ResourceClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClassList. +func (in *ResourceClassList) DeepCopy() *ResourceClassList { + if in == nil { + return nil + } + out := new(ResourceClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ResourceClassList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceClassParametersReference) DeepCopyInto(out *ResourceClassParametersReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceClassParametersReference. +func (in *ResourceClassParametersReference) DeepCopy() *ResourceClassParametersReference { + if in == nil { + return nil + } + out := new(ResourceClassParametersReference) + in.DeepCopyInto(out) + return out +} diff --git a/staging/src/k8s.io/api/roundtrip_test.go b/staging/src/k8s.io/api/roundtrip_test.go index 004b2fc341b..1c326766fe5 100644 --- a/staging/src/k8s.io/api/roundtrip_test.go +++ b/staging/src/k8s.io/api/roundtrip_test.go @@ -66,6 +66,7 @@ import ( rbacv1 "k8s.io/api/rbac/v1" rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" schedulingv1 "k8s.io/api/scheduling/v1" schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" @@ -128,6 +129,7 @@ var groups = []runtime.SchemeBuilder{ rbacv1alpha1.SchemeBuilder, rbacv1beta1.SchemeBuilder, rbacv1.SchemeBuilder, + resourcev1alpha1.SchemeBuilder, schedulingv1alpha1.SchemeBuilder, schedulingv1beta1.SchemeBuilder, schedulingv1.SchemeBuilder, diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.json b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.json index 738a6262fe2..3be60ec71c3 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.json +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.json @@ -452,7 +452,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -539,7 +544,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -811,7 +821,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1083,7 +1098,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1632,6 +1652,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.pb b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.pb index 3be2f777dd8..3bab9bf0d81 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.pb and b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.yaml b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.yaml index af8f209a00b..2a4e76faaf8 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.DaemonSet.yaml @@ -313,6 +313,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -514,6 +516,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -717,6 +721,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -799,6 +805,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -967,6 +978,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.json b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.json index dafac19bb22..4e816305973 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.json +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.json @@ -453,7 +453,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -540,7 +545,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -812,7 +822,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1084,7 +1099,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1633,6 +1653,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.pb b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.pb index 59bdf8abf2f..d6b5ef6d6ee 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.pb and b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.yaml b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.yaml index c8151f68c4a..95eb1cf5ba6 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.Deployment.yaml @@ -321,6 +321,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -522,6 +524,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -725,6 +729,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -807,6 +813,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -975,6 +986,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.ReplicaSet.json b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.ReplicaSet.json index 1c8dce80b92..602aa71fc15 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.ReplicaSet.json +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.ReplicaSet.json @@ -454,7 +454,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -541,7 +546,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -813,7 +823,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1085,7 +1100,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1634,6 +1654,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } } diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.ReplicaSet.pb b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.ReplicaSet.pb index 8b244cdd8f2..21bdb0b88cc 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.ReplicaSet.pb and b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.ReplicaSet.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.ReplicaSet.yaml b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.ReplicaSet.yaml index 7847af5aad7..428a9330493 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.ReplicaSet.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.ReplicaSet.yaml @@ -313,6 +313,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -514,6 +516,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -717,6 +721,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -799,6 +805,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -967,6 +978,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.StatefulSet.json b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.StatefulSet.json index f2bcbc148f2..d734f79d5ad 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.StatefulSet.json +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.StatefulSet.json @@ -453,7 +453,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -540,7 +545,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -812,7 +822,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1084,7 +1099,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1633,6 +1653,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, @@ -1704,7 +1733,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.StatefulSet.pb b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.StatefulSet.pb index 98328c384bb..ca5e950c178 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.StatefulSet.pb and b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.StatefulSet.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.StatefulSet.yaml b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.StatefulSet.yaml index 7d5e459b6e1..65f6ba4c505 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1.StatefulSet.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1.StatefulSet.yaml @@ -321,6 +321,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -522,6 +524,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -725,6 +729,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -807,6 +813,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -975,6 +986,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -1187,6 +1200,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.Deployment.json b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.Deployment.json index c7c846ee8b8..d10076e9fab 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.Deployment.json +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.Deployment.json @@ -453,7 +453,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -540,7 +545,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -812,7 +822,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1084,7 +1099,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1633,6 +1653,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.Deployment.pb b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.Deployment.pb index 56120ac8cf6..b0c417c946a 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.Deployment.pb and b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.Deployment.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.Deployment.yaml b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.Deployment.yaml index a3a28763017..ddec9327700 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.Deployment.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.Deployment.yaml @@ -323,6 +323,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -524,6 +526,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -727,6 +731,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -809,6 +815,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -977,6 +988,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.StatefulSet.json b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.StatefulSet.json index ed6bc5ea22c..a11eea31669 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.StatefulSet.json +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.StatefulSet.json @@ -453,7 +453,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -540,7 +545,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -812,7 +822,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1084,7 +1099,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1633,6 +1653,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, @@ -1704,7 +1733,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.StatefulSet.pb b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.StatefulSet.pb index a21cff7a91c..b639e14b47e 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.StatefulSet.pb and b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.StatefulSet.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.StatefulSet.yaml b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.StatefulSet.yaml index e7accde44a8..4e69533963d 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.StatefulSet.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta1.StatefulSet.yaml @@ -321,6 +321,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -522,6 +524,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -725,6 +729,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -807,6 +813,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -975,6 +986,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -1187,6 +1200,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.DaemonSet.json b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.DaemonSet.json index e688d3dc2f4..6f8d7697d34 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.DaemonSet.json +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.DaemonSet.json @@ -452,7 +452,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -539,7 +544,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -811,7 +821,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1083,7 +1098,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1632,6 +1652,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.DaemonSet.pb b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.DaemonSet.pb index 85a4a42dde5..0dc29469dbd 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.DaemonSet.pb and b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.DaemonSet.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.DaemonSet.yaml b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.DaemonSet.yaml index c86d3c7e23c..d7e537f36db 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.DaemonSet.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.DaemonSet.yaml @@ -313,6 +313,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -514,6 +516,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -717,6 +721,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -799,6 +805,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -967,6 +978,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.Deployment.json b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.Deployment.json index bdfdf88cb0c..1d5153db5a1 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.Deployment.json +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.Deployment.json @@ -453,7 +453,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -540,7 +545,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -812,7 +822,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1084,7 +1099,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1633,6 +1653,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.Deployment.pb b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.Deployment.pb index 126c3415208..80500415d68 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.Deployment.pb and b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.Deployment.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.Deployment.yaml b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.Deployment.yaml index 25961b6f6fc..ac65063f9d9 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.Deployment.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.Deployment.yaml @@ -321,6 +321,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -522,6 +524,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -725,6 +729,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -807,6 +813,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -975,6 +986,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.ReplicaSet.json b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.ReplicaSet.json index 27c85a19150..205eac84fa3 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.ReplicaSet.json +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.ReplicaSet.json @@ -454,7 +454,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -541,7 +546,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -813,7 +823,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1085,7 +1100,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1634,6 +1654,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } } diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.ReplicaSet.pb b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.ReplicaSet.pb index 779c5aff486..6a4bea5910c 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.ReplicaSet.pb and b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.ReplicaSet.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.ReplicaSet.yaml b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.ReplicaSet.yaml index cb7a2832753..f924c9f9e11 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.ReplicaSet.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.ReplicaSet.yaml @@ -313,6 +313,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -514,6 +516,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -717,6 +721,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -799,6 +805,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -967,6 +978,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.StatefulSet.json b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.StatefulSet.json index 8cad36c601a..a51539af605 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.StatefulSet.json +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.StatefulSet.json @@ -453,7 +453,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -540,7 +545,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -812,7 +822,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1084,7 +1099,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1633,6 +1653,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, @@ -1704,7 +1733,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.StatefulSet.pb b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.StatefulSet.pb index 6835199453e..6f400f403e1 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.StatefulSet.pb and b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.StatefulSet.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.StatefulSet.yaml b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.StatefulSet.yaml index 417a6e08333..188440b9c7f 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.StatefulSet.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/apps.v1beta2.StatefulSet.yaml @@ -321,6 +321,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -522,6 +524,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -725,6 +729,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -807,6 +813,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -975,6 +986,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -1187,6 +1200,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/batch.v1.CronJob.json b/staging/src/k8s.io/api/testdata/HEAD/batch.v1.CronJob.json index f8924f0deb4..9f2b1fc3bdd 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/batch.v1.CronJob.json +++ b/staging/src/k8s.io/api/testdata/HEAD/batch.v1.CronJob.json @@ -526,7 +526,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -613,7 +618,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -885,7 +895,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1157,7 +1172,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1706,6 +1726,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, diff --git a/staging/src/k8s.io/api/testdata/HEAD/batch.v1.CronJob.pb b/staging/src/k8s.io/api/testdata/HEAD/batch.v1.CronJob.pb index ffe76eb932d..8cd7ebdc40c 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/batch.v1.CronJob.pb and b/staging/src/k8s.io/api/testdata/HEAD/batch.v1.CronJob.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/batch.v1.CronJob.yaml b/staging/src/k8s.io/api/testdata/HEAD/batch.v1.CronJob.yaml index e463690b728..05bdfcc75d7 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/batch.v1.CronJob.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/batch.v1.CronJob.yaml @@ -365,6 +365,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -566,6 +568,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -769,6 +773,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -851,6 +857,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -1019,6 +1030,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.json b/staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.json index 814b4d0b20c..d35c8a28b51 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.json +++ b/staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.json @@ -477,7 +477,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -564,7 +569,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -836,7 +846,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1108,7 +1123,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1657,6 +1677,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, diff --git a/staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.pb b/staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.pb index 622f1302dfa..5d932c3ae30 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.pb and b/staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.yaml b/staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.yaml index 7985d12e991..67ffd1e2149 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.yaml @@ -329,6 +329,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -530,6 +532,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -733,6 +737,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -815,6 +821,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -983,6 +994,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.CronJob.json b/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.CronJob.json index 8f038e7a26b..e9340df2366 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.CronJob.json +++ b/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.CronJob.json @@ -526,7 +526,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -613,7 +618,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -885,7 +895,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1157,7 +1172,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1706,6 +1726,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, diff --git a/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.CronJob.pb b/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.CronJob.pb index 98ada33e7e4..1b0b676c3ec 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.CronJob.pb and b/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.CronJob.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.CronJob.yaml b/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.CronJob.yaml index 35ca72f8b0e..01448a84f6d 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.CronJob.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.CronJob.yaml @@ -365,6 +365,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -566,6 +568,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -769,6 +773,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -851,6 +857,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -1019,6 +1030,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.JobTemplate.json b/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.JobTemplate.json index bc6fc0d6076..00fe2b0f133 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.JobTemplate.json +++ b/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.JobTemplate.json @@ -520,7 +520,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -607,7 +612,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -879,7 +889,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1151,7 +1166,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1700,6 +1720,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, diff --git a/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.JobTemplate.pb b/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.JobTemplate.pb index c12c0b1988d..253ea811f21 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.JobTemplate.pb and b/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.JobTemplate.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.JobTemplate.yaml b/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.JobTemplate.yaml index 3fc7398f5c1..a9d88bfa293 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.JobTemplate.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/batch.v1beta1.JobTemplate.yaml @@ -362,6 +362,8 @@ template: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -563,6 +565,8 @@ template: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -766,6 +770,8 @@ template: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -848,6 +854,11 @@ template: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -1016,6 +1027,8 @@ template: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.PersistentVolumeClaim.json b/staging/src/k8s.io/api/testdata/HEAD/core.v1.PersistentVolumeClaim.json index 2fcd9a1bc5f..4f0eb722fb6 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/core.v1.PersistentVolumeClaim.json +++ b/staging/src/k8s.io/api/testdata/HEAD/core.v1.PersistentVolumeClaim.json @@ -67,7 +67,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.PersistentVolumeClaim.pb b/staging/src/k8s.io/api/testdata/HEAD/core.v1.PersistentVolumeClaim.pb index fb08edfee5b..5504385eb00 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/core.v1.PersistentVolumeClaim.pb and b/staging/src/k8s.io/api/testdata/HEAD/core.v1.PersistentVolumeClaim.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.PersistentVolumeClaim.yaml b/staging/src/k8s.io/api/testdata/HEAD/core.v1.PersistentVolumeClaim.yaml index f91c3e83f7e..d758ebdb8fd 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/core.v1.PersistentVolumeClaim.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/core.v1.PersistentVolumeClaim.yaml @@ -45,6 +45,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.json b/staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.json index 2cb051c418c..c8318d4d009 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.json +++ b/staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.json @@ -394,7 +394,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -481,7 +486,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -753,7 +763,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1025,7 +1040,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1574,6 +1594,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] }, "status": { diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.pb b/staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.pb index 6453885b2c5..8b18232560d 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.pb and b/staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.yaml b/staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.yaml index 905e57cbf00..ddf86d6da45 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.yaml @@ -269,6 +269,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -470,6 +472,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -673,6 +677,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -755,6 +761,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -923,6 +934,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.PodTemplate.json b/staging/src/k8s.io/api/testdata/HEAD/core.v1.PodTemplate.json index e5dce99a8d2..4ec4455dd57 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/core.v1.PodTemplate.json +++ b/staging/src/k8s.io/api/testdata/HEAD/core.v1.PodTemplate.json @@ -437,7 +437,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -524,7 +529,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -796,7 +806,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1068,7 +1083,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1617,6 +1637,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } } diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.PodTemplate.pb b/staging/src/k8s.io/api/testdata/HEAD/core.v1.PodTemplate.pb index 1d9d2c5c97d..bb4ed25ca81 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/core.v1.PodTemplate.pb and b/staging/src/k8s.io/api/testdata/HEAD/core.v1.PodTemplate.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.PodTemplate.yaml b/staging/src/k8s.io/api/testdata/HEAD/core.v1.PodTemplate.yaml index 7a87881ccf9..b867c9b6e44 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/core.v1.PodTemplate.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/core.v1.PodTemplate.yaml @@ -302,6 +302,8 @@ template: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -503,6 +505,8 @@ template: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -706,6 +710,8 @@ template: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -788,6 +794,11 @@ template: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -956,6 +967,8 @@ template: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.ReplicationController.json b/staging/src/k8s.io/api/testdata/HEAD/core.v1.ReplicationController.json index 345db29615d..88d8649defd 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/core.v1.ReplicationController.json +++ b/staging/src/k8s.io/api/testdata/HEAD/core.v1.ReplicationController.json @@ -443,7 +443,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -530,7 +535,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -802,7 +812,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1074,7 +1089,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1623,6 +1643,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } } diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.ReplicationController.pb b/staging/src/k8s.io/api/testdata/HEAD/core.v1.ReplicationController.pb index b9b57d85367..2084b4b469a 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/core.v1.ReplicationController.pb and b/staging/src/k8s.io/api/testdata/HEAD/core.v1.ReplicationController.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.ReplicationController.yaml b/staging/src/k8s.io/api/testdata/HEAD/core.v1.ReplicationController.yaml index d5c3711da15..3c2e609d533 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/core.v1.ReplicationController.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/core.v1.ReplicationController.yaml @@ -307,6 +307,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -508,6 +510,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -711,6 +715,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -793,6 +799,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -961,6 +972,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.DaemonSet.json b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.DaemonSet.json index 2ae4e1a61a9..c44c130c594 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.DaemonSet.json +++ b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.DaemonSet.json @@ -452,7 +452,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -539,7 +544,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -811,7 +821,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1083,7 +1098,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1632,6 +1652,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, diff --git a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.DaemonSet.pb b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.DaemonSet.pb index 25a7c5d2629..68da0e878aa 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.DaemonSet.pb and b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.DaemonSet.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.DaemonSet.yaml b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.DaemonSet.yaml index c098bb447ae..16b473bd901 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.DaemonSet.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.DaemonSet.yaml @@ -313,6 +313,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -514,6 +516,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -717,6 +721,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -799,6 +805,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -967,6 +978,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.Deployment.json b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.Deployment.json index fb690e084a7..47755b78ab0 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.Deployment.json +++ b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.Deployment.json @@ -453,7 +453,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -540,7 +545,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -812,7 +822,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1084,7 +1099,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1633,6 +1653,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } }, diff --git a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.Deployment.pb b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.Deployment.pb index 329354d1c17..a963e7fa181 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.Deployment.pb and b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.Deployment.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.Deployment.yaml b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.Deployment.yaml index 9a075556187..64ec8b09f89 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.Deployment.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.Deployment.yaml @@ -323,6 +323,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -524,6 +526,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -727,6 +731,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -809,6 +815,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -977,6 +988,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.ReplicaSet.json b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.ReplicaSet.json index 8a6ff2e3b17..120b8797d01 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.ReplicaSet.json +++ b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.ReplicaSet.json @@ -454,7 +454,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeName": "volumeNameValue", "storageClassName": "storageClassNameValue", @@ -541,7 +546,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -813,7 +823,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1085,7 +1100,12 @@ }, "requests": { "requestsKey": "0" - } + }, + "claims": [ + { + "name": "nameValue" + } + ] }, "volumeMounts": [ { @@ -1634,6 +1654,15 @@ { "name": "nameValue" } + ], + "resourceClaims": [ + { + "name": "nameValue", + "source": { + "resourceClaimName": "resourceClaimNameValue", + "resourceClaimTemplateName": "resourceClaimTemplateNameValue" + } + } ] } } diff --git a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.ReplicaSet.pb b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.ReplicaSet.pb index fc81a5b9320..792be95deae 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.ReplicaSet.pb and b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.ReplicaSet.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.ReplicaSet.yaml b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.ReplicaSet.yaml index ac712f2ac99..af52541be1c 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.ReplicaSet.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/extensions.v1beta1.ReplicaSet.yaml @@ -313,6 +313,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -514,6 +516,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -717,6 +721,8 @@ spec: terminationGracePeriodSeconds: 7 timeoutSeconds: 3 resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: @@ -799,6 +805,11 @@ spec: priorityClassName: priorityClassNameValue readinessGates: - conditionType: conditionTypeValue + resourceClaims: + - name: nameValue + source: + resourceClaimName: resourceClaimNameValue + resourceClaimTemplateName: resourceClaimTemplateNameValue restartPolicy: restartPolicyValue runtimeClassName: runtimeClassNameValue schedulerName: schedulerNameValue @@ -967,6 +978,8 @@ spec: name: nameValue namespace: namespaceValue resources: + claims: + - name: nameValue limits: limitsKey: "0" requests: diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.PodScheduling.json b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.PodScheduling.json new file mode 100644 index 00000000000..5590555162c --- /dev/null +++ b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.PodScheduling.json @@ -0,0 +1,62 @@ +{ + "kind": "PodScheduling", + "apiVersion": "resource.k8s.io/v1alpha1", + "metadata": { + "name": "nameValue", + "generateName": "generateNameValue", + "namespace": "namespaceValue", + "selfLink": "selfLinkValue", + "uid": "uidValue", + "resourceVersion": "resourceVersionValue", + "generation": 7, + "creationTimestamp": "2008-01-01T01:01:01Z", + "deletionTimestamp": "2009-01-01T01:01:01Z", + "deletionGracePeriodSeconds": 10, + "labels": { + "labelsKey": "labelsValue" + }, + "annotations": { + "annotationsKey": "annotationsValue" + }, + "ownerReferences": [ + { + "apiVersion": "apiVersionValue", + "kind": "kindValue", + "name": "nameValue", + "uid": "uidValue", + "controller": true, + "blockOwnerDeletion": true + } + ], + "finalizers": [ + "finalizersValue" + ], + "managedFields": [ + { + "manager": "managerValue", + "operation": "operationValue", + "apiVersion": "apiVersionValue", + "time": "2004-01-01T01:01:01Z", + "fieldsType": "fieldsTypeValue", + "fieldsV1": {}, + "subresource": "subresourceValue" + } + ] + }, + "spec": { + "selectedNode": "selectedNodeValue", + "potentialNodes": [ + "potentialNodesValue" + ] + }, + "status": { + "resourceClaims": [ + { + "name": "nameValue", + "unsuitableNodes": [ + "unsuitableNodesValue" + ] + } + ] + } +} \ No newline at end of file diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.PodScheduling.pb b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.PodScheduling.pb new file mode 100644 index 00000000000..4dc9623d52c Binary files /dev/null and b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.PodScheduling.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.PodScheduling.yaml b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.PodScheduling.yaml new file mode 100644 index 00000000000..6f5627deec8 --- /dev/null +++ b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.PodScheduling.yaml @@ -0,0 +1,43 @@ +apiVersion: resource.k8s.io/v1alpha1 +kind: PodScheduling +metadata: + annotations: + annotationsKey: annotationsValue + creationTimestamp: "2008-01-01T01:01:01Z" + deletionGracePeriodSeconds: 10 + deletionTimestamp: "2009-01-01T01:01:01Z" + finalizers: + - finalizersValue + generateName: generateNameValue + generation: 7 + labels: + labelsKey: labelsValue + managedFields: + - apiVersion: apiVersionValue + fieldsType: fieldsTypeValue + fieldsV1: {} + manager: managerValue + operation: operationValue + subresource: subresourceValue + time: "2004-01-01T01:01:01Z" + name: nameValue + namespace: namespaceValue + ownerReferences: + - apiVersion: apiVersionValue + blockOwnerDeletion: true + controller: true + kind: kindValue + name: nameValue + uid: uidValue + resourceVersion: resourceVersionValue + selfLink: selfLinkValue + uid: uidValue +spec: + potentialNodes: + - potentialNodesValue + selectedNode: selectedNodeValue +status: + resourceClaims: + - name: nameValue + unsuitableNodes: + - unsuitableNodesValue diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaim.json b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaim.json new file mode 100644 index 00000000000..f1501251c69 --- /dev/null +++ b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaim.json @@ -0,0 +1,95 @@ +{ + "kind": "ResourceClaim", + "apiVersion": "resource.k8s.io/v1alpha1", + "metadata": { + "name": "nameValue", + "generateName": "generateNameValue", + "namespace": "namespaceValue", + "selfLink": "selfLinkValue", + "uid": "uidValue", + "resourceVersion": "resourceVersionValue", + "generation": 7, + "creationTimestamp": "2008-01-01T01:01:01Z", + "deletionTimestamp": "2009-01-01T01:01:01Z", + "deletionGracePeriodSeconds": 10, + "labels": { + "labelsKey": "labelsValue" + }, + "annotations": { + "annotationsKey": "annotationsValue" + }, + "ownerReferences": [ + { + "apiVersion": "apiVersionValue", + "kind": "kindValue", + "name": "nameValue", + "uid": "uidValue", + "controller": true, + "blockOwnerDeletion": true + } + ], + "finalizers": [ + "finalizersValue" + ], + "managedFields": [ + { + "manager": "managerValue", + "operation": "operationValue", + "apiVersion": "apiVersionValue", + "time": "2004-01-01T01:01:01Z", + "fieldsType": "fieldsTypeValue", + "fieldsV1": {}, + "subresource": "subresourceValue" + } + ] + }, + "spec": { + "resourceClassName": "resourceClassNameValue", + "parametersRef": { + "apiGroup": "apiGroupValue", + "kind": "kindValue", + "name": "nameValue" + }, + "allocationMode": "allocationModeValue" + }, + "status": { + "driverName": "driverNameValue", + "allocation": { + "resourceHandle": "resourceHandleValue", + "availableOnNodes": { + "nodeSelectorTerms": [ + { + "matchExpressions": [ + { + "key": "keyValue", + "operator": "operatorValue", + "values": [ + "valuesValue" + ] + } + ], + "matchFields": [ + { + "key": "keyValue", + "operator": "operatorValue", + "values": [ + "valuesValue" + ] + } + ] + } + ] + }, + "shareable": true + }, + "reservedFor": [ + { + "apiGroup": "apiGroupValue", + "resource": "resourceValue", + "name": "nameValue", + "uid": "uidValue" + } + ], + "deallocationRequested": true + } +} \ No newline at end of file diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaim.pb b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaim.pb new file mode 100644 index 00000000000..c50b8f0126d Binary files /dev/null and b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaim.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaim.yaml b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaim.yaml new file mode 100644 index 00000000000..d7b52c4e160 --- /dev/null +++ b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaim.yaml @@ -0,0 +1,64 @@ +apiVersion: resource.k8s.io/v1alpha1 +kind: ResourceClaim +metadata: + annotations: + annotationsKey: annotationsValue + creationTimestamp: "2008-01-01T01:01:01Z" + deletionGracePeriodSeconds: 10 + deletionTimestamp: "2009-01-01T01:01:01Z" + finalizers: + - finalizersValue + generateName: generateNameValue + generation: 7 + labels: + labelsKey: labelsValue + managedFields: + - apiVersion: apiVersionValue + fieldsType: fieldsTypeValue + fieldsV1: {} + manager: managerValue + operation: operationValue + subresource: subresourceValue + time: "2004-01-01T01:01:01Z" + name: nameValue + namespace: namespaceValue + ownerReferences: + - apiVersion: apiVersionValue + blockOwnerDeletion: true + controller: true + kind: kindValue + name: nameValue + uid: uidValue + resourceVersion: resourceVersionValue + selfLink: selfLinkValue + uid: uidValue +spec: + allocationMode: allocationModeValue + parametersRef: + apiGroup: apiGroupValue + kind: kindValue + name: nameValue + resourceClassName: resourceClassNameValue +status: + allocation: + availableOnNodes: + nodeSelectorTerms: + - matchExpressions: + - key: keyValue + operator: operatorValue + values: + - valuesValue + matchFields: + - key: keyValue + operator: operatorValue + values: + - valuesValue + resourceHandle: resourceHandleValue + shareable: true + deallocationRequested: true + driverName: driverNameValue + reservedFor: + - apiGroup: apiGroupValue + name: nameValue + resource: resourceValue + uid: uidValue diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaimTemplate.json b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaimTemplate.json new file mode 100644 index 00000000000..12358250d4f --- /dev/null +++ b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaimTemplate.json @@ -0,0 +1,99 @@ +{ + "kind": "ResourceClaimTemplate", + "apiVersion": "resource.k8s.io/v1alpha1", + "metadata": { + "name": "nameValue", + "generateName": "generateNameValue", + "namespace": "namespaceValue", + "selfLink": "selfLinkValue", + "uid": "uidValue", + "resourceVersion": "resourceVersionValue", + "generation": 7, + "creationTimestamp": "2008-01-01T01:01:01Z", + "deletionTimestamp": "2009-01-01T01:01:01Z", + "deletionGracePeriodSeconds": 10, + "labels": { + "labelsKey": "labelsValue" + }, + "annotations": { + "annotationsKey": "annotationsValue" + }, + "ownerReferences": [ + { + "apiVersion": "apiVersionValue", + "kind": "kindValue", + "name": "nameValue", + "uid": "uidValue", + "controller": true, + "blockOwnerDeletion": true + } + ], + "finalizers": [ + "finalizersValue" + ], + "managedFields": [ + { + "manager": "managerValue", + "operation": "operationValue", + "apiVersion": "apiVersionValue", + "time": "2004-01-01T01:01:01Z", + "fieldsType": "fieldsTypeValue", + "fieldsV1": {}, + "subresource": "subresourceValue" + } + ] + }, + "spec": { + "metadata": { + "name": "nameValue", + "generateName": "generateNameValue", + "namespace": "namespaceValue", + "selfLink": "selfLinkValue", + "uid": "uidValue", + "resourceVersion": "resourceVersionValue", + "generation": 7, + "creationTimestamp": "2008-01-01T01:01:01Z", + "deletionTimestamp": "2009-01-01T01:01:01Z", + "deletionGracePeriodSeconds": 10, + "labels": { + "labelsKey": "labelsValue" + }, + "annotations": { + "annotationsKey": "annotationsValue" + }, + "ownerReferences": [ + { + "apiVersion": "apiVersionValue", + "kind": "kindValue", + "name": "nameValue", + "uid": "uidValue", + "controller": true, + "blockOwnerDeletion": true + } + ], + "finalizers": [ + "finalizersValue" + ], + "managedFields": [ + { + "manager": "managerValue", + "operation": "operationValue", + "apiVersion": "apiVersionValue", + "time": "2004-01-01T01:01:01Z", + "fieldsType": "fieldsTypeValue", + "fieldsV1": {}, + "subresource": "subresourceValue" + } + ] + }, + "spec": { + "resourceClassName": "resourceClassNameValue", + "parametersRef": { + "apiGroup": "apiGroupValue", + "kind": "kindValue", + "name": "nameValue" + }, + "allocationMode": "allocationModeValue" + } + } +} \ No newline at end of file diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaimTemplate.pb b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaimTemplate.pb new file mode 100644 index 00000000000..7177e570fcd Binary files /dev/null and b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaimTemplate.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaimTemplate.yaml b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaimTemplate.yaml new file mode 100644 index 00000000000..6204ec79ccd --- /dev/null +++ b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClaimTemplate.yaml @@ -0,0 +1,74 @@ +apiVersion: resource.k8s.io/v1alpha1 +kind: ResourceClaimTemplate +metadata: + annotations: + annotationsKey: annotationsValue + creationTimestamp: "2008-01-01T01:01:01Z" + deletionGracePeriodSeconds: 10 + deletionTimestamp: "2009-01-01T01:01:01Z" + finalizers: + - finalizersValue + generateName: generateNameValue + generation: 7 + labels: + labelsKey: labelsValue + managedFields: + - apiVersion: apiVersionValue + fieldsType: fieldsTypeValue + fieldsV1: {} + manager: managerValue + operation: operationValue + subresource: subresourceValue + time: "2004-01-01T01:01:01Z" + name: nameValue + namespace: namespaceValue + ownerReferences: + - apiVersion: apiVersionValue + blockOwnerDeletion: true + controller: true + kind: kindValue + name: nameValue + uid: uidValue + resourceVersion: resourceVersionValue + selfLink: selfLinkValue + uid: uidValue +spec: + metadata: + annotations: + annotationsKey: annotationsValue + creationTimestamp: "2008-01-01T01:01:01Z" + deletionGracePeriodSeconds: 10 + deletionTimestamp: "2009-01-01T01:01:01Z" + finalizers: + - finalizersValue + generateName: generateNameValue + generation: 7 + labels: + labelsKey: labelsValue + managedFields: + - apiVersion: apiVersionValue + fieldsType: fieldsTypeValue + fieldsV1: {} + manager: managerValue + operation: operationValue + subresource: subresourceValue + time: "2004-01-01T01:01:01Z" + name: nameValue + namespace: namespaceValue + ownerReferences: + - apiVersion: apiVersionValue + blockOwnerDeletion: true + controller: true + kind: kindValue + name: nameValue + uid: uidValue + resourceVersion: resourceVersionValue + selfLink: selfLinkValue + uid: uidValue + spec: + allocationMode: allocationModeValue + parametersRef: + apiGroup: apiGroupValue + kind: kindValue + name: nameValue + resourceClassName: resourceClassNameValue diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClass.json b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClass.json new file mode 100644 index 00000000000..a40268178a9 --- /dev/null +++ b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClass.json @@ -0,0 +1,77 @@ +{ + "kind": "ResourceClass", + "apiVersion": "resource.k8s.io/v1alpha1", + "metadata": { + "name": "nameValue", + "generateName": "generateNameValue", + "namespace": "namespaceValue", + "selfLink": "selfLinkValue", + "uid": "uidValue", + "resourceVersion": "resourceVersionValue", + "generation": 7, + "creationTimestamp": "2008-01-01T01:01:01Z", + "deletionTimestamp": "2009-01-01T01:01:01Z", + "deletionGracePeriodSeconds": 10, + "labels": { + "labelsKey": "labelsValue" + }, + "annotations": { + "annotationsKey": "annotationsValue" + }, + "ownerReferences": [ + { + "apiVersion": "apiVersionValue", + "kind": "kindValue", + "name": "nameValue", + "uid": "uidValue", + "controller": true, + "blockOwnerDeletion": true + } + ], + "finalizers": [ + "finalizersValue" + ], + "managedFields": [ + { + "manager": "managerValue", + "operation": "operationValue", + "apiVersion": "apiVersionValue", + "time": "2004-01-01T01:01:01Z", + "fieldsType": "fieldsTypeValue", + "fieldsV1": {}, + "subresource": "subresourceValue" + } + ] + }, + "driverName": "driverNameValue", + "parametersRef": { + "apiGroup": "apiGroupValue", + "kind": "kindValue", + "name": "nameValue", + "namespace": "namespaceValue" + }, + "suitableNodes": { + "nodeSelectorTerms": [ + { + "matchExpressions": [ + { + "key": "keyValue", + "operator": "operatorValue", + "values": [ + "valuesValue" + ] + } + ], + "matchFields": [ + { + "key": "keyValue", + "operator": "operatorValue", + "values": [ + "valuesValue" + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClass.pb b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClass.pb new file mode 100644 index 00000000000..fef3714f662 Binary files /dev/null and b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClass.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClass.yaml b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClass.yaml new file mode 100644 index 00000000000..251d6a2bfd1 --- /dev/null +++ b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.ResourceClass.yaml @@ -0,0 +1,52 @@ +apiVersion: resource.k8s.io/v1alpha1 +driverName: driverNameValue +kind: ResourceClass +metadata: + annotations: + annotationsKey: annotationsValue + creationTimestamp: "2008-01-01T01:01:01Z" + deletionGracePeriodSeconds: 10 + deletionTimestamp: "2009-01-01T01:01:01Z" + finalizers: + - finalizersValue + generateName: generateNameValue + generation: 7 + labels: + labelsKey: labelsValue + managedFields: + - apiVersion: apiVersionValue + fieldsType: fieldsTypeValue + fieldsV1: {} + manager: managerValue + operation: operationValue + subresource: subresourceValue + time: "2004-01-01T01:01:01Z" + name: nameValue + namespace: namespaceValue + ownerReferences: + - apiVersion: apiVersionValue + blockOwnerDeletion: true + controller: true + kind: kindValue + name: nameValue + uid: uidValue + resourceVersion: resourceVersionValue + selfLink: selfLinkValue + uid: uidValue +parametersRef: + apiGroup: apiGroupValue + kind: kindValue + name: nameValue + namespace: namespaceValue +suitableNodes: + nodeSelectorTerms: + - matchExpressions: + - key: keyValue + operator: operatorValue + values: + - valuesValue + matchFields: + - key: keyValue + operator: operatorValue + values: + - valuesValue diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.Status.json b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.Status.json new file mode 100644 index 00000000000..13e0bdbcbef --- /dev/null +++ b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.Status.json @@ -0,0 +1,28 @@ +{ + "kind": "Status", + "apiVersion": "resource.k8s.io/v1alpha1", + "metadata": { + "selfLink": "selfLinkValue", + "resourceVersion": "resourceVersionValue", + "continue": "continueValue", + "remainingItemCount": 4 + }, + "status": "statusValue", + "message": "messageValue", + "reason": "reasonValue", + "details": { + "name": "nameValue", + "group": "groupValue", + "kind": "kindValue", + "uid": "uidValue", + "causes": [ + { + "reason": "reasonValue", + "message": "messageValue", + "field": "fieldValue" + } + ], + "retryAfterSeconds": 5 + }, + "code": 6 +} \ No newline at end of file diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.Status.pb b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.Status.pb new file mode 100644 index 00000000000..ac73b5ccdfb Binary files /dev/null and b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.Status.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.Status.yaml b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.Status.yaml new file mode 100644 index 00000000000..f78f424e9c9 --- /dev/null +++ b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha1.Status.yaml @@ -0,0 +1,21 @@ +apiVersion: resource.k8s.io/v1alpha1 +code: 6 +details: + causes: + - field: fieldValue + message: messageValue + reason: reasonValue + group: groupValue + kind: kindValue + name: nameValue + retryAfterSeconds: 5 + uid: uidValue +kind: Status +message: messageValue +metadata: + continue: continueValue + remainingItemCount: 4 + resourceVersion: resourceVersionValue + selfLink: selfLinkValue +reason: reasonValue +status: statusValue diff --git a/staging/src/k8s.io/client-go/applyconfigurations/core/v1/claimsource.go b/staging/src/k8s.io/client-go/applyconfigurations/core/v1/claimsource.go new file mode 100644 index 00000000000..2153570fc08 --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/core/v1/claimsource.go @@ -0,0 +1,48 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +// ClaimSourceApplyConfiguration represents an declarative configuration of the ClaimSource type for use +// with apply. +type ClaimSourceApplyConfiguration struct { + ResourceClaimName *string `json:"resourceClaimName,omitempty"` + ResourceClaimTemplateName *string `json:"resourceClaimTemplateName,omitempty"` +} + +// ClaimSourceApplyConfiguration constructs an declarative configuration of the ClaimSource type for use with +// apply. +func ClaimSource() *ClaimSourceApplyConfiguration { + return &ClaimSourceApplyConfiguration{} +} + +// WithResourceClaimName sets the ResourceClaimName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceClaimName field is set to the value of the last call. +func (b *ClaimSourceApplyConfiguration) WithResourceClaimName(value string) *ClaimSourceApplyConfiguration { + b.ResourceClaimName = &value + return b +} + +// WithResourceClaimTemplateName sets the ResourceClaimTemplateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceClaimTemplateName field is set to the value of the last call. +func (b *ClaimSourceApplyConfiguration) WithResourceClaimTemplateName(value string) *ClaimSourceApplyConfiguration { + b.ResourceClaimTemplateName = &value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/core/v1/podresourceclaim.go b/staging/src/k8s.io/client-go/applyconfigurations/core/v1/podresourceclaim.go new file mode 100644 index 00000000000..69b250d474f --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/core/v1/podresourceclaim.go @@ -0,0 +1,48 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +// PodResourceClaimApplyConfiguration represents an declarative configuration of the PodResourceClaim type for use +// with apply. +type PodResourceClaimApplyConfiguration struct { + Name *string `json:"name,omitempty"` + Source *ClaimSourceApplyConfiguration `json:"source,omitempty"` +} + +// PodResourceClaimApplyConfiguration constructs an declarative configuration of the PodResourceClaim type for use with +// apply. +func PodResourceClaim() *PodResourceClaimApplyConfiguration { + return &PodResourceClaimApplyConfiguration{} +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *PodResourceClaimApplyConfiguration) WithName(value string) *PodResourceClaimApplyConfiguration { + b.Name = &value + return b +} + +// WithSource sets the Source field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Source field is set to the value of the last call. +func (b *PodResourceClaimApplyConfiguration) WithSource(value *ClaimSourceApplyConfiguration) *PodResourceClaimApplyConfiguration { + b.Source = value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/core/v1/podspec.go b/staging/src/k8s.io/client-go/applyconfigurations/core/v1/podspec.go index 984c6160128..a9acd36fc7c 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/core/v1/podspec.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/core/v1/podspec.go @@ -63,6 +63,7 @@ type PodSpecApplyConfiguration struct { OS *PodOSApplyConfiguration `json:"os,omitempty"` HostUsers *bool `json:"hostUsers,omitempty"` SchedulingGates []PodSchedulingGateApplyConfiguration `json:"schedulingGates,omitempty"` + ResourceClaims []PodResourceClaimApplyConfiguration `json:"resourceClaims,omitempty"` } // PodSpecApplyConfiguration constructs an declarative configuration of the PodSpec type for use with @@ -430,3 +431,16 @@ func (b *PodSpecApplyConfiguration) WithSchedulingGates(values ...*PodScheduling } return b } + +// WithResourceClaims adds the given value to the ResourceClaims field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the ResourceClaims field. +func (b *PodSpecApplyConfiguration) WithResourceClaims(values ...*PodResourceClaimApplyConfiguration) *PodSpecApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithResourceClaims") + } + b.ResourceClaims = append(b.ResourceClaims, *values[i]) + } + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/core/v1/resourceclaim.go b/staging/src/k8s.io/client-go/applyconfigurations/core/v1/resourceclaim.go new file mode 100644 index 00000000000..064dd4e2e41 --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/core/v1/resourceclaim.go @@ -0,0 +1,39 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +// ResourceClaimApplyConfiguration represents an declarative configuration of the ResourceClaim type for use +// with apply. +type ResourceClaimApplyConfiguration struct { + Name *string `json:"name,omitempty"` +} + +// ResourceClaimApplyConfiguration constructs an declarative configuration of the ResourceClaim type for use with +// apply. +func ResourceClaim() *ResourceClaimApplyConfiguration { + return &ResourceClaimApplyConfiguration{} +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithName(value string) *ResourceClaimApplyConfiguration { + b.Name = &value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/core/v1/resourcerequirements.go b/staging/src/k8s.io/client-go/applyconfigurations/core/v1/resourcerequirements.go index d22f3847945..9482b8d7134 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/core/v1/resourcerequirements.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/core/v1/resourcerequirements.go @@ -25,8 +25,9 @@ import ( // ResourceRequirementsApplyConfiguration represents an declarative configuration of the ResourceRequirements type for use // with apply. type ResourceRequirementsApplyConfiguration struct { - Limits *v1.ResourceList `json:"limits,omitempty"` - Requests *v1.ResourceList `json:"requests,omitempty"` + Limits *v1.ResourceList `json:"limits,omitempty"` + Requests *v1.ResourceList `json:"requests,omitempty"` + Claims []ResourceClaimApplyConfiguration `json:"claims,omitempty"` } // ResourceRequirementsApplyConfiguration constructs an declarative configuration of the ResourceRequirements type for use with @@ -50,3 +51,16 @@ func (b *ResourceRequirementsApplyConfiguration) WithRequests(value v1.ResourceL b.Requests = &value return b } + +// WithClaims adds the given value to the Claims field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Claims field. +func (b *ResourceRequirementsApplyConfiguration) WithClaims(values ...*ResourceClaimApplyConfiguration) *ResourceRequirementsApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithClaims") + } + b.Claims = append(b.Claims, *values[i]) + } + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/internal/internal.go b/staging/src/k8s.io/client-go/applyconfigurations/internal/internal.go index 4c6f70139fc..afad3b12e18 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/internal/internal.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/internal/internal.go @@ -3916,6 +3916,15 @@ var schemaYAML = typed.YAMLObject(`types: type: scalar: string default: "" +- name: io.k8s.api.core.v1.ClaimSource + map: + fields: + - name: resourceClaimName + type: + scalar: string + - name: resourceClaimTemplateName + type: + scalar: string - name: io.k8s.api.core.v1.ClientIPConfig map: fields: @@ -5884,6 +5893,17 @@ var schemaYAML = typed.YAMLObject(`types: type: scalar: string default: "" +- name: io.k8s.api.core.v1.PodResourceClaim + map: + fields: + - name: name + type: + scalar: string + default: "" + - name: source + type: + namedType: io.k8s.api.core.v1.ClaimSource + default: {} - name: io.k8s.api.core.v1.PodSchedulingGate map: fields: @@ -6038,6 +6058,14 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.api.core.v1.PodReadinessGate elementRelationship: atomic + - name: resourceClaims + type: + list: + elementType: + namedType: io.k8s.api.core.v1.PodResourceClaim + elementRelationship: associative + keys: + - name - name: restartPolicy type: scalar: string @@ -6443,6 +6471,13 @@ var schemaYAML = typed.YAMLObject(`types: type: scalar: numeric default: 0 +- name: io.k8s.api.core.v1.ResourceClaim + map: + fields: + - name: name + type: + scalar: string + default: "" - name: io.k8s.api.core.v1.ResourceFieldSelector map: fields: @@ -6512,6 +6547,12 @@ var schemaYAML = typed.YAMLObject(`types: - name: io.k8s.api.core.v1.ResourceRequirements map: fields: + - name: claims + type: + list: + elementType: + namedType: io.k8s.api.core.v1.ResourceClaim + elementRelationship: associative - name: limits type: map: @@ -11466,6 +11507,226 @@ var schemaYAML = typed.YAMLObject(`types: - name: namespace type: scalar: string +- name: io.k8s.api.resource.v1alpha1.AllocationResult + map: + fields: + - name: availableOnNodes + type: + namedType: io.k8s.api.core.v1.NodeSelector + - name: resourceHandle + type: + scalar: string + - name: shareable + type: + scalar: boolean +- name: io.k8s.api.resource.v1alpha1.PodScheduling + map: + fields: + - name: apiVersion + type: + scalar: string + - name: kind + type: + scalar: string + - name: metadata + type: + namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta + default: {} + - name: spec + type: + namedType: io.k8s.api.resource.v1alpha1.PodSchedulingSpec + default: {} + - name: status + type: + namedType: io.k8s.api.resource.v1alpha1.PodSchedulingStatus + default: {} +- name: io.k8s.api.resource.v1alpha1.PodSchedulingSpec + map: + fields: + - name: potentialNodes + type: + list: + elementType: + scalar: string + elementRelationship: associative + - name: selectedNode + type: + scalar: string +- name: io.k8s.api.resource.v1alpha1.PodSchedulingStatus + map: + fields: + - name: resourceClaims + type: + list: + elementType: + namedType: io.k8s.api.resource.v1alpha1.ResourceClaimSchedulingStatus + elementRelationship: associative + keys: + - name +- name: io.k8s.api.resource.v1alpha1.ResourceClaim + map: + fields: + - name: apiVersion + type: + scalar: string + - name: kind + type: + scalar: string + - name: metadata + type: + namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta + default: {} + - name: spec + type: + namedType: io.k8s.api.resource.v1alpha1.ResourceClaimSpec + default: {} + - name: status + type: + namedType: io.k8s.api.resource.v1alpha1.ResourceClaimStatus + default: {} +- name: io.k8s.api.resource.v1alpha1.ResourceClaimConsumerReference + map: + fields: + - name: apiGroup + type: + scalar: string + - name: name + type: + scalar: string + default: "" + - name: resource + type: + scalar: string + default: "" + - name: uid + type: + scalar: string + default: "" +- name: io.k8s.api.resource.v1alpha1.ResourceClaimParametersReference + map: + fields: + - name: apiGroup + type: + scalar: string + - name: kind + type: + scalar: string + default: "" + - name: name + type: + scalar: string + default: "" +- name: io.k8s.api.resource.v1alpha1.ResourceClaimSchedulingStatus + map: + fields: + - name: name + type: + scalar: string + - name: unsuitableNodes + type: + list: + elementType: + scalar: string + elementRelationship: associative +- name: io.k8s.api.resource.v1alpha1.ResourceClaimSpec + map: + fields: + - name: allocationMode + type: + scalar: string + - name: parametersRef + type: + namedType: io.k8s.api.resource.v1alpha1.ResourceClaimParametersReference + - name: resourceClassName + type: + scalar: string + default: "" +- name: io.k8s.api.resource.v1alpha1.ResourceClaimStatus + map: + fields: + - name: allocation + type: + namedType: io.k8s.api.resource.v1alpha1.AllocationResult + - name: deallocationRequested + type: + scalar: boolean + - name: driverName + type: + scalar: string + - name: reservedFor + type: + list: + elementType: + namedType: io.k8s.api.resource.v1alpha1.ResourceClaimConsumerReference + elementRelationship: associative +- name: io.k8s.api.resource.v1alpha1.ResourceClaimTemplate + map: + fields: + - name: apiVersion + type: + scalar: string + - name: kind + type: + scalar: string + - name: metadata + type: + namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta + default: {} + - name: spec + type: + namedType: io.k8s.api.resource.v1alpha1.ResourceClaimTemplateSpec + default: {} +- name: io.k8s.api.resource.v1alpha1.ResourceClaimTemplateSpec + map: + fields: + - name: metadata + type: + namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta + default: {} + - name: spec + type: + namedType: io.k8s.api.resource.v1alpha1.ResourceClaimSpec + default: {} +- name: io.k8s.api.resource.v1alpha1.ResourceClass + map: + fields: + - name: apiVersion + type: + scalar: string + - name: driverName + type: + scalar: string + default: "" + - name: kind + type: + scalar: string + - name: metadata + type: + namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta + default: {} + - name: parametersRef + type: + namedType: io.k8s.api.resource.v1alpha1.ResourceClassParametersReference + - name: suitableNodes + type: + namedType: io.k8s.api.core.v1.NodeSelector +- name: io.k8s.api.resource.v1alpha1.ResourceClassParametersReference + map: + fields: + - name: apiGroup + type: + scalar: string + - name: kind + type: + scalar: string + default: "" + - name: name + type: + scalar: string + default: "" + - name: namespace + type: + scalar: string - name: io.k8s.api.scheduling.v1.PriorityClass map: fields: diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/allocationresult.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/allocationresult.go new file mode 100644 index 00000000000..a2ad3adf1af --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/allocationresult.go @@ -0,0 +1,61 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/client-go/applyconfigurations/core/v1" +) + +// AllocationResultApplyConfiguration represents an declarative configuration of the AllocationResult type for use +// with apply. +type AllocationResultApplyConfiguration struct { + ResourceHandle *string `json:"resourceHandle,omitempty"` + AvailableOnNodes *v1.NodeSelectorApplyConfiguration `json:"availableOnNodes,omitempty"` + Shareable *bool `json:"shareable,omitempty"` +} + +// AllocationResultApplyConfiguration constructs an declarative configuration of the AllocationResult type for use with +// apply. +func AllocationResult() *AllocationResultApplyConfiguration { + return &AllocationResultApplyConfiguration{} +} + +// WithResourceHandle sets the ResourceHandle field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceHandle field is set to the value of the last call. +func (b *AllocationResultApplyConfiguration) WithResourceHandle(value string) *AllocationResultApplyConfiguration { + b.ResourceHandle = &value + return b +} + +// WithAvailableOnNodes sets the AvailableOnNodes field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the AvailableOnNodes field is set to the value of the last call. +func (b *AllocationResultApplyConfiguration) WithAvailableOnNodes(value *v1.NodeSelectorApplyConfiguration) *AllocationResultApplyConfiguration { + b.AvailableOnNodes = value + return b +} + +// WithShareable sets the Shareable field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Shareable field is set to the value of the last call. +func (b *AllocationResultApplyConfiguration) WithShareable(value bool) *AllocationResultApplyConfiguration { + b.Shareable = &value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/podscheduling.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/podscheduling.go new file mode 100644 index 00000000000..44890c2d92e --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/podscheduling.go @@ -0,0 +1,258 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + managedfields "k8s.io/apimachinery/pkg/util/managedfields" + internal "k8s.io/client-go/applyconfigurations/internal" + v1 "k8s.io/client-go/applyconfigurations/meta/v1" +) + +// PodSchedulingApplyConfiguration represents an declarative configuration of the PodScheduling type for use +// with apply. +type PodSchedulingApplyConfiguration struct { + v1.TypeMetaApplyConfiguration `json:",inline"` + *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + Spec *PodSchedulingSpecApplyConfiguration `json:"spec,omitempty"` + Status *PodSchedulingStatusApplyConfiguration `json:"status,omitempty"` +} + +// PodScheduling constructs an declarative configuration of the PodScheduling type for use with +// apply. +func PodScheduling(name, namespace string) *PodSchedulingApplyConfiguration { + b := &PodSchedulingApplyConfiguration{} + b.WithName(name) + b.WithNamespace(namespace) + b.WithKind("PodScheduling") + b.WithAPIVersion("resource.k8s.io/v1alpha1") + return b +} + +// ExtractPodScheduling extracts the applied configuration owned by fieldManager from +// podScheduling. If no managedFields are found in podScheduling for fieldManager, a +// PodSchedulingApplyConfiguration is returned with only the Name, Namespace (if applicable), +// APIVersion and Kind populated. It is possible that no managed fields were found for because other +// field managers have taken ownership of all the fields previously owned by fieldManager, or because +// the fieldManager never owned fields any fields. +// podScheduling must be a unmodified PodScheduling API object that was retrieved from the Kubernetes API. +// ExtractPodScheduling provides a way to perform a extract/modify-in-place/apply workflow. +// Note that an extracted apply configuration will contain fewer fields than what the fieldManager previously +// applied if another fieldManager has updated or force applied any of the previously applied fields. +// Experimental! +func ExtractPodScheduling(podScheduling *resourcev1alpha1.PodScheduling, fieldManager string) (*PodSchedulingApplyConfiguration, error) { + return extractPodScheduling(podScheduling, fieldManager, "") +} + +// ExtractPodSchedulingStatus is the same as ExtractPodScheduling except +// that it extracts the status subresource applied configuration. +// Experimental! +func ExtractPodSchedulingStatus(podScheduling *resourcev1alpha1.PodScheduling, fieldManager string) (*PodSchedulingApplyConfiguration, error) { + return extractPodScheduling(podScheduling, fieldManager, "status") +} + +func extractPodScheduling(podScheduling *resourcev1alpha1.PodScheduling, fieldManager string, subresource string) (*PodSchedulingApplyConfiguration, error) { + b := &PodSchedulingApplyConfiguration{} + err := managedfields.ExtractInto(podScheduling, internal.Parser().Type("io.k8s.api.resource.v1alpha1.PodScheduling"), fieldManager, b, subresource) + if err != nil { + return nil, err + } + b.WithName(podScheduling.Name) + b.WithNamespace(podScheduling.Namespace) + + b.WithKind("PodScheduling") + b.WithAPIVersion("resource.k8s.io/v1alpha1") + return b, nil +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithKind(value string) *PodSchedulingApplyConfiguration { + b.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithAPIVersion(value string) *PodSchedulingApplyConfiguration { + b.APIVersion = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithName(value string) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithGenerateName(value string) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithNamespace(value string) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithUID(value types.UID) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithResourceVersion(value string) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithGeneration(value int64) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithCreationTimestamp(value metav1.Time) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *PodSchedulingApplyConfiguration) WithLabels(entries map[string]string) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Labels == nil && len(entries) > 0 { + b.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *PodSchedulingApplyConfiguration) WithAnnotations(entries map[string]string) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Annotations == nil && len(entries) > 0 { + b.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *PodSchedulingApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.OwnerReferences = append(b.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *PodSchedulingApplyConfiguration) WithFinalizers(values ...string) *PodSchedulingApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.Finalizers = append(b.Finalizers, values[i]) + } + return b +} + +func (b *PodSchedulingApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{} + } +} + +// WithSpec sets the Spec field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Spec field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithSpec(value *PodSchedulingSpecApplyConfiguration) *PodSchedulingApplyConfiguration { + b.Spec = value + return b +} + +// WithStatus sets the Status field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Status field is set to the value of the last call. +func (b *PodSchedulingApplyConfiguration) WithStatus(value *PodSchedulingStatusApplyConfiguration) *PodSchedulingApplyConfiguration { + b.Status = value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/podschedulingspec.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/podschedulingspec.go new file mode 100644 index 00000000000..9fd3c1ee53e --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/podschedulingspec.go @@ -0,0 +1,50 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +// PodSchedulingSpecApplyConfiguration represents an declarative configuration of the PodSchedulingSpec type for use +// with apply. +type PodSchedulingSpecApplyConfiguration struct { + SelectedNode *string `json:"selectedNode,omitempty"` + PotentialNodes []string `json:"potentialNodes,omitempty"` +} + +// PodSchedulingSpecApplyConfiguration constructs an declarative configuration of the PodSchedulingSpec type for use with +// apply. +func PodSchedulingSpec() *PodSchedulingSpecApplyConfiguration { + return &PodSchedulingSpecApplyConfiguration{} +} + +// WithSelectedNode sets the SelectedNode field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SelectedNode field is set to the value of the last call. +func (b *PodSchedulingSpecApplyConfiguration) WithSelectedNode(value string) *PodSchedulingSpecApplyConfiguration { + b.SelectedNode = &value + return b +} + +// WithPotentialNodes adds the given value to the PotentialNodes field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the PotentialNodes field. +func (b *PodSchedulingSpecApplyConfiguration) WithPotentialNodes(values ...string) *PodSchedulingSpecApplyConfiguration { + for i := range values { + b.PotentialNodes = append(b.PotentialNodes, values[i]) + } + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/podschedulingstatus.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/podschedulingstatus.go new file mode 100644 index 00000000000..5744f6c3eb2 --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/podschedulingstatus.go @@ -0,0 +1,44 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +// PodSchedulingStatusApplyConfiguration represents an declarative configuration of the PodSchedulingStatus type for use +// with apply. +type PodSchedulingStatusApplyConfiguration struct { + ResourceClaims []ResourceClaimSchedulingStatusApplyConfiguration `json:"resourceClaims,omitempty"` +} + +// PodSchedulingStatusApplyConfiguration constructs an declarative configuration of the PodSchedulingStatus type for use with +// apply. +func PodSchedulingStatus() *PodSchedulingStatusApplyConfiguration { + return &PodSchedulingStatusApplyConfiguration{} +} + +// WithResourceClaims adds the given value to the ResourceClaims field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the ResourceClaims field. +func (b *PodSchedulingStatusApplyConfiguration) WithResourceClaims(values ...*ResourceClaimSchedulingStatusApplyConfiguration) *PodSchedulingStatusApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithResourceClaims") + } + b.ResourceClaims = append(b.ResourceClaims, *values[i]) + } + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaim.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaim.go new file mode 100644 index 00000000000..f94811a9b10 --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaim.go @@ -0,0 +1,258 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + managedfields "k8s.io/apimachinery/pkg/util/managedfields" + internal "k8s.io/client-go/applyconfigurations/internal" + v1 "k8s.io/client-go/applyconfigurations/meta/v1" +) + +// ResourceClaimApplyConfiguration represents an declarative configuration of the ResourceClaim type for use +// with apply. +type ResourceClaimApplyConfiguration struct { + v1.TypeMetaApplyConfiguration `json:",inline"` + *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + Spec *ResourceClaimSpecApplyConfiguration `json:"spec,omitempty"` + Status *ResourceClaimStatusApplyConfiguration `json:"status,omitempty"` +} + +// ResourceClaim constructs an declarative configuration of the ResourceClaim type for use with +// apply. +func ResourceClaim(name, namespace string) *ResourceClaimApplyConfiguration { + b := &ResourceClaimApplyConfiguration{} + b.WithName(name) + b.WithNamespace(namespace) + b.WithKind("ResourceClaim") + b.WithAPIVersion("resource.k8s.io/v1alpha1") + return b +} + +// ExtractResourceClaim extracts the applied configuration owned by fieldManager from +// resourceClaim. If no managedFields are found in resourceClaim for fieldManager, a +// ResourceClaimApplyConfiguration is returned with only the Name, Namespace (if applicable), +// APIVersion and Kind populated. It is possible that no managed fields were found for because other +// field managers have taken ownership of all the fields previously owned by fieldManager, or because +// the fieldManager never owned fields any fields. +// resourceClaim must be a unmodified ResourceClaim API object that was retrieved from the Kubernetes API. +// ExtractResourceClaim provides a way to perform a extract/modify-in-place/apply workflow. +// Note that an extracted apply configuration will contain fewer fields than what the fieldManager previously +// applied if another fieldManager has updated or force applied any of the previously applied fields. +// Experimental! +func ExtractResourceClaim(resourceClaim *resourcev1alpha1.ResourceClaim, fieldManager string) (*ResourceClaimApplyConfiguration, error) { + return extractResourceClaim(resourceClaim, fieldManager, "") +} + +// ExtractResourceClaimStatus is the same as ExtractResourceClaim except +// that it extracts the status subresource applied configuration. +// Experimental! +func ExtractResourceClaimStatus(resourceClaim *resourcev1alpha1.ResourceClaim, fieldManager string) (*ResourceClaimApplyConfiguration, error) { + return extractResourceClaim(resourceClaim, fieldManager, "status") +} + +func extractResourceClaim(resourceClaim *resourcev1alpha1.ResourceClaim, fieldManager string, subresource string) (*ResourceClaimApplyConfiguration, error) { + b := &ResourceClaimApplyConfiguration{} + err := managedfields.ExtractInto(resourceClaim, internal.Parser().Type("io.k8s.api.resource.v1alpha1.ResourceClaim"), fieldManager, b, subresource) + if err != nil { + return nil, err + } + b.WithName(resourceClaim.Name) + b.WithNamespace(resourceClaim.Namespace) + + b.WithKind("ResourceClaim") + b.WithAPIVersion("resource.k8s.io/v1alpha1") + return b, nil +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithKind(value string) *ResourceClaimApplyConfiguration { + b.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithAPIVersion(value string) *ResourceClaimApplyConfiguration { + b.APIVersion = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithName(value string) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithGenerateName(value string) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithNamespace(value string) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithUID(value types.UID) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithResourceVersion(value string) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithGeneration(value int64) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithCreationTimestamp(value metav1.Time) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *ResourceClaimApplyConfiguration) WithLabels(entries map[string]string) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Labels == nil && len(entries) > 0 { + b.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *ResourceClaimApplyConfiguration) WithAnnotations(entries map[string]string) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Annotations == nil && len(entries) > 0 { + b.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *ResourceClaimApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.OwnerReferences = append(b.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *ResourceClaimApplyConfiguration) WithFinalizers(values ...string) *ResourceClaimApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.Finalizers = append(b.Finalizers, values[i]) + } + return b +} + +func (b *ResourceClaimApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{} + } +} + +// WithSpec sets the Spec field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Spec field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithSpec(value *ResourceClaimSpecApplyConfiguration) *ResourceClaimApplyConfiguration { + b.Spec = value + return b +} + +// WithStatus sets the Status field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Status field is set to the value of the last call. +func (b *ResourceClaimApplyConfiguration) WithStatus(value *ResourceClaimStatusApplyConfiguration) *ResourceClaimApplyConfiguration { + b.Status = value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimconsumerreference.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimconsumerreference.go new file mode 100644 index 00000000000..477099cd7a0 --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimconsumerreference.go @@ -0,0 +1,70 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + types "k8s.io/apimachinery/pkg/types" +) + +// ResourceClaimConsumerReferenceApplyConfiguration represents an declarative configuration of the ResourceClaimConsumerReference type for use +// with apply. +type ResourceClaimConsumerReferenceApplyConfiguration struct { + APIGroup *string `json:"apiGroup,omitempty"` + Resource *string `json:"resource,omitempty"` + Name *string `json:"name,omitempty"` + UID *types.UID `json:"uid,omitempty"` +} + +// ResourceClaimConsumerReferenceApplyConfiguration constructs an declarative configuration of the ResourceClaimConsumerReference type for use with +// apply. +func ResourceClaimConsumerReference() *ResourceClaimConsumerReferenceApplyConfiguration { + return &ResourceClaimConsumerReferenceApplyConfiguration{} +} + +// WithAPIGroup sets the APIGroup field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIGroup field is set to the value of the last call. +func (b *ResourceClaimConsumerReferenceApplyConfiguration) WithAPIGroup(value string) *ResourceClaimConsumerReferenceApplyConfiguration { + b.APIGroup = &value + return b +} + +// WithResource sets the Resource field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Resource field is set to the value of the last call. +func (b *ResourceClaimConsumerReferenceApplyConfiguration) WithResource(value string) *ResourceClaimConsumerReferenceApplyConfiguration { + b.Resource = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *ResourceClaimConsumerReferenceApplyConfiguration) WithName(value string) *ResourceClaimConsumerReferenceApplyConfiguration { + b.Name = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *ResourceClaimConsumerReferenceApplyConfiguration) WithUID(value types.UID) *ResourceClaimConsumerReferenceApplyConfiguration { + b.UID = &value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimparametersreference.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimparametersreference.go new file mode 100644 index 00000000000..d7b25d75eb4 --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimparametersreference.go @@ -0,0 +1,57 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +// ResourceClaimParametersReferenceApplyConfiguration represents an declarative configuration of the ResourceClaimParametersReference type for use +// with apply. +type ResourceClaimParametersReferenceApplyConfiguration struct { + APIGroup *string `json:"apiGroup,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` +} + +// ResourceClaimParametersReferenceApplyConfiguration constructs an declarative configuration of the ResourceClaimParametersReference type for use with +// apply. +func ResourceClaimParametersReference() *ResourceClaimParametersReferenceApplyConfiguration { + return &ResourceClaimParametersReferenceApplyConfiguration{} +} + +// WithAPIGroup sets the APIGroup field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIGroup field is set to the value of the last call. +func (b *ResourceClaimParametersReferenceApplyConfiguration) WithAPIGroup(value string) *ResourceClaimParametersReferenceApplyConfiguration { + b.APIGroup = &value + return b +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *ResourceClaimParametersReferenceApplyConfiguration) WithKind(value string) *ResourceClaimParametersReferenceApplyConfiguration { + b.Kind = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *ResourceClaimParametersReferenceApplyConfiguration) WithName(value string) *ResourceClaimParametersReferenceApplyConfiguration { + b.Name = &value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimschedulingstatus.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimschedulingstatus.go new file mode 100644 index 00000000000..35ff34abab2 --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimschedulingstatus.go @@ -0,0 +1,50 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +// ResourceClaimSchedulingStatusApplyConfiguration represents an declarative configuration of the ResourceClaimSchedulingStatus type for use +// with apply. +type ResourceClaimSchedulingStatusApplyConfiguration struct { + Name *string `json:"name,omitempty"` + UnsuitableNodes []string `json:"unsuitableNodes,omitempty"` +} + +// ResourceClaimSchedulingStatusApplyConfiguration constructs an declarative configuration of the ResourceClaimSchedulingStatus type for use with +// apply. +func ResourceClaimSchedulingStatus() *ResourceClaimSchedulingStatusApplyConfiguration { + return &ResourceClaimSchedulingStatusApplyConfiguration{} +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *ResourceClaimSchedulingStatusApplyConfiguration) WithName(value string) *ResourceClaimSchedulingStatusApplyConfiguration { + b.Name = &value + return b +} + +// WithUnsuitableNodes adds the given value to the UnsuitableNodes field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the UnsuitableNodes field. +func (b *ResourceClaimSchedulingStatusApplyConfiguration) WithUnsuitableNodes(values ...string) *ResourceClaimSchedulingStatusApplyConfiguration { + for i := range values { + b.UnsuitableNodes = append(b.UnsuitableNodes, values[i]) + } + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimspec.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimspec.go new file mode 100644 index 00000000000..d3261904627 --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimspec.go @@ -0,0 +1,61 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" +) + +// ResourceClaimSpecApplyConfiguration represents an declarative configuration of the ResourceClaimSpec type for use +// with apply. +type ResourceClaimSpecApplyConfiguration struct { + ResourceClassName *string `json:"resourceClassName,omitempty"` + ParametersRef *ResourceClaimParametersReferenceApplyConfiguration `json:"parametersRef,omitempty"` + AllocationMode *resourcev1alpha1.AllocationMode `json:"allocationMode,omitempty"` +} + +// ResourceClaimSpecApplyConfiguration constructs an declarative configuration of the ResourceClaimSpec type for use with +// apply. +func ResourceClaimSpec() *ResourceClaimSpecApplyConfiguration { + return &ResourceClaimSpecApplyConfiguration{} +} + +// WithResourceClassName sets the ResourceClassName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceClassName field is set to the value of the last call. +func (b *ResourceClaimSpecApplyConfiguration) WithResourceClassName(value string) *ResourceClaimSpecApplyConfiguration { + b.ResourceClassName = &value + return b +} + +// WithParametersRef sets the ParametersRef field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ParametersRef field is set to the value of the last call. +func (b *ResourceClaimSpecApplyConfiguration) WithParametersRef(value *ResourceClaimParametersReferenceApplyConfiguration) *ResourceClaimSpecApplyConfiguration { + b.ParametersRef = value + return b +} + +// WithAllocationMode sets the AllocationMode field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the AllocationMode field is set to the value of the last call. +func (b *ResourceClaimSpecApplyConfiguration) WithAllocationMode(value resourcev1alpha1.AllocationMode) *ResourceClaimSpecApplyConfiguration { + b.AllocationMode = &value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimstatus.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimstatus.go new file mode 100644 index 00000000000..e2283f8b07f --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimstatus.go @@ -0,0 +1,71 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +// ResourceClaimStatusApplyConfiguration represents an declarative configuration of the ResourceClaimStatus type for use +// with apply. +type ResourceClaimStatusApplyConfiguration struct { + DriverName *string `json:"driverName,omitempty"` + Allocation *AllocationResultApplyConfiguration `json:"allocation,omitempty"` + ReservedFor []ResourceClaimConsumerReferenceApplyConfiguration `json:"reservedFor,omitempty"` + DeallocationRequested *bool `json:"deallocationRequested,omitempty"` +} + +// ResourceClaimStatusApplyConfiguration constructs an declarative configuration of the ResourceClaimStatus type for use with +// apply. +func ResourceClaimStatus() *ResourceClaimStatusApplyConfiguration { + return &ResourceClaimStatusApplyConfiguration{} +} + +// WithDriverName sets the DriverName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DriverName field is set to the value of the last call. +func (b *ResourceClaimStatusApplyConfiguration) WithDriverName(value string) *ResourceClaimStatusApplyConfiguration { + b.DriverName = &value + return b +} + +// WithAllocation sets the Allocation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Allocation field is set to the value of the last call. +func (b *ResourceClaimStatusApplyConfiguration) WithAllocation(value *AllocationResultApplyConfiguration) *ResourceClaimStatusApplyConfiguration { + b.Allocation = value + return b +} + +// WithReservedFor adds the given value to the ReservedFor field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the ReservedFor field. +func (b *ResourceClaimStatusApplyConfiguration) WithReservedFor(values ...*ResourceClaimConsumerReferenceApplyConfiguration) *ResourceClaimStatusApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithReservedFor") + } + b.ReservedFor = append(b.ReservedFor, *values[i]) + } + return b +} + +// WithDeallocationRequested sets the DeallocationRequested field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeallocationRequested field is set to the value of the last call. +func (b *ResourceClaimStatusApplyConfiguration) WithDeallocationRequested(value bool) *ResourceClaimStatusApplyConfiguration { + b.DeallocationRequested = &value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimtemplate.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimtemplate.go new file mode 100644 index 00000000000..e3c602cb652 --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimtemplate.go @@ -0,0 +1,249 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + managedfields "k8s.io/apimachinery/pkg/util/managedfields" + internal "k8s.io/client-go/applyconfigurations/internal" + v1 "k8s.io/client-go/applyconfigurations/meta/v1" +) + +// ResourceClaimTemplateApplyConfiguration represents an declarative configuration of the ResourceClaimTemplate type for use +// with apply. +type ResourceClaimTemplateApplyConfiguration struct { + v1.TypeMetaApplyConfiguration `json:",inline"` + *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + Spec *ResourceClaimTemplateSpecApplyConfiguration `json:"spec,omitempty"` +} + +// ResourceClaimTemplate constructs an declarative configuration of the ResourceClaimTemplate type for use with +// apply. +func ResourceClaimTemplate(name, namespace string) *ResourceClaimTemplateApplyConfiguration { + b := &ResourceClaimTemplateApplyConfiguration{} + b.WithName(name) + b.WithNamespace(namespace) + b.WithKind("ResourceClaimTemplate") + b.WithAPIVersion("resource.k8s.io/v1alpha1") + return b +} + +// ExtractResourceClaimTemplate extracts the applied configuration owned by fieldManager from +// resourceClaimTemplate. If no managedFields are found in resourceClaimTemplate for fieldManager, a +// ResourceClaimTemplateApplyConfiguration is returned with only the Name, Namespace (if applicable), +// APIVersion and Kind populated. It is possible that no managed fields were found for because other +// field managers have taken ownership of all the fields previously owned by fieldManager, or because +// the fieldManager never owned fields any fields. +// resourceClaimTemplate must be a unmodified ResourceClaimTemplate API object that was retrieved from the Kubernetes API. +// ExtractResourceClaimTemplate provides a way to perform a extract/modify-in-place/apply workflow. +// Note that an extracted apply configuration will contain fewer fields than what the fieldManager previously +// applied if another fieldManager has updated or force applied any of the previously applied fields. +// Experimental! +func ExtractResourceClaimTemplate(resourceClaimTemplate *resourcev1alpha1.ResourceClaimTemplate, fieldManager string) (*ResourceClaimTemplateApplyConfiguration, error) { + return extractResourceClaimTemplate(resourceClaimTemplate, fieldManager, "") +} + +// ExtractResourceClaimTemplateStatus is the same as ExtractResourceClaimTemplate except +// that it extracts the status subresource applied configuration. +// Experimental! +func ExtractResourceClaimTemplateStatus(resourceClaimTemplate *resourcev1alpha1.ResourceClaimTemplate, fieldManager string) (*ResourceClaimTemplateApplyConfiguration, error) { + return extractResourceClaimTemplate(resourceClaimTemplate, fieldManager, "status") +} + +func extractResourceClaimTemplate(resourceClaimTemplate *resourcev1alpha1.ResourceClaimTemplate, fieldManager string, subresource string) (*ResourceClaimTemplateApplyConfiguration, error) { + b := &ResourceClaimTemplateApplyConfiguration{} + err := managedfields.ExtractInto(resourceClaimTemplate, internal.Parser().Type("io.k8s.api.resource.v1alpha1.ResourceClaimTemplate"), fieldManager, b, subresource) + if err != nil { + return nil, err + } + b.WithName(resourceClaimTemplate.Name) + b.WithNamespace(resourceClaimTemplate.Namespace) + + b.WithKind("ResourceClaimTemplate") + b.WithAPIVersion("resource.k8s.io/v1alpha1") + return b, nil +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *ResourceClaimTemplateApplyConfiguration) WithKind(value string) *ResourceClaimTemplateApplyConfiguration { + b.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *ResourceClaimTemplateApplyConfiguration) WithAPIVersion(value string) *ResourceClaimTemplateApplyConfiguration { + b.APIVersion = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *ResourceClaimTemplateApplyConfiguration) WithName(value string) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *ResourceClaimTemplateApplyConfiguration) WithGenerateName(value string) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *ResourceClaimTemplateApplyConfiguration) WithNamespace(value string) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *ResourceClaimTemplateApplyConfiguration) WithUID(value types.UID) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *ResourceClaimTemplateApplyConfiguration) WithResourceVersion(value string) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *ResourceClaimTemplateApplyConfiguration) WithGeneration(value int64) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *ResourceClaimTemplateApplyConfiguration) WithCreationTimestamp(value metav1.Time) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *ResourceClaimTemplateApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *ResourceClaimTemplateApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *ResourceClaimTemplateApplyConfiguration) WithLabels(entries map[string]string) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Labels == nil && len(entries) > 0 { + b.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *ResourceClaimTemplateApplyConfiguration) WithAnnotations(entries map[string]string) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Annotations == nil && len(entries) > 0 { + b.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *ResourceClaimTemplateApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.OwnerReferences = append(b.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *ResourceClaimTemplateApplyConfiguration) WithFinalizers(values ...string) *ResourceClaimTemplateApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.Finalizers = append(b.Finalizers, values[i]) + } + return b +} + +func (b *ResourceClaimTemplateApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{} + } +} + +// WithSpec sets the Spec field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Spec field is set to the value of the last call. +func (b *ResourceClaimTemplateApplyConfiguration) WithSpec(value *ResourceClaimTemplateSpecApplyConfiguration) *ResourceClaimTemplateApplyConfiguration { + b.Spec = value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimtemplatespec.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimtemplatespec.go new file mode 100644 index 00000000000..88058e066e1 --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclaimtemplatespec.go @@ -0,0 +1,188 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + v1 "k8s.io/client-go/applyconfigurations/meta/v1" +) + +// ResourceClaimTemplateSpecApplyConfiguration represents an declarative configuration of the ResourceClaimTemplateSpec type for use +// with apply. +type ResourceClaimTemplateSpecApplyConfiguration struct { + *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + Spec *ResourceClaimSpecApplyConfiguration `json:"spec,omitempty"` +} + +// ResourceClaimTemplateSpecApplyConfiguration constructs an declarative configuration of the ResourceClaimTemplateSpec type for use with +// apply. +func ResourceClaimTemplateSpec() *ResourceClaimTemplateSpecApplyConfiguration { + return &ResourceClaimTemplateSpecApplyConfiguration{} +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithName(value string) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithGenerateName(value string) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithNamespace(value string) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithUID(value types.UID) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithResourceVersion(value string) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithGeneration(value int64) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithCreationTimestamp(value metav1.Time) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithLabels(entries map[string]string) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Labels == nil && len(entries) > 0 { + b.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithAnnotations(entries map[string]string) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Annotations == nil && len(entries) > 0 { + b.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.OwnerReferences = append(b.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithFinalizers(values ...string) *ResourceClaimTemplateSpecApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.Finalizers = append(b.Finalizers, values[i]) + } + return b +} + +func (b *ResourceClaimTemplateSpecApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{} + } +} + +// WithSpec sets the Spec field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Spec field is set to the value of the last call. +func (b *ResourceClaimTemplateSpecApplyConfiguration) WithSpec(value *ResourceClaimSpecApplyConfiguration) *ResourceClaimTemplateSpecApplyConfiguration { + b.Spec = value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclass.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclass.go new file mode 100644 index 00000000000..5f980acdb1f --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclass.go @@ -0,0 +1,266 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + managedfields "k8s.io/apimachinery/pkg/util/managedfields" + corev1 "k8s.io/client-go/applyconfigurations/core/v1" + internal "k8s.io/client-go/applyconfigurations/internal" + v1 "k8s.io/client-go/applyconfigurations/meta/v1" +) + +// ResourceClassApplyConfiguration represents an declarative configuration of the ResourceClass type for use +// with apply. +type ResourceClassApplyConfiguration struct { + v1.TypeMetaApplyConfiguration `json:",inline"` + *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + DriverName *string `json:"driverName,omitempty"` + ParametersRef *ResourceClassParametersReferenceApplyConfiguration `json:"parametersRef,omitempty"` + SuitableNodes *corev1.NodeSelectorApplyConfiguration `json:"suitableNodes,omitempty"` +} + +// ResourceClass constructs an declarative configuration of the ResourceClass type for use with +// apply. +func ResourceClass(name string) *ResourceClassApplyConfiguration { + b := &ResourceClassApplyConfiguration{} + b.WithName(name) + b.WithKind("ResourceClass") + b.WithAPIVersion("resource.k8s.io/v1alpha1") + return b +} + +// ExtractResourceClass extracts the applied configuration owned by fieldManager from +// resourceClass. If no managedFields are found in resourceClass for fieldManager, a +// ResourceClassApplyConfiguration is returned with only the Name, Namespace (if applicable), +// APIVersion and Kind populated. It is possible that no managed fields were found for because other +// field managers have taken ownership of all the fields previously owned by fieldManager, or because +// the fieldManager never owned fields any fields. +// resourceClass must be a unmodified ResourceClass API object that was retrieved from the Kubernetes API. +// ExtractResourceClass provides a way to perform a extract/modify-in-place/apply workflow. +// Note that an extracted apply configuration will contain fewer fields than what the fieldManager previously +// applied if another fieldManager has updated or force applied any of the previously applied fields. +// Experimental! +func ExtractResourceClass(resourceClass *resourcev1alpha1.ResourceClass, fieldManager string) (*ResourceClassApplyConfiguration, error) { + return extractResourceClass(resourceClass, fieldManager, "") +} + +// ExtractResourceClassStatus is the same as ExtractResourceClass except +// that it extracts the status subresource applied configuration. +// Experimental! +func ExtractResourceClassStatus(resourceClass *resourcev1alpha1.ResourceClass, fieldManager string) (*ResourceClassApplyConfiguration, error) { + return extractResourceClass(resourceClass, fieldManager, "status") +} + +func extractResourceClass(resourceClass *resourcev1alpha1.ResourceClass, fieldManager string, subresource string) (*ResourceClassApplyConfiguration, error) { + b := &ResourceClassApplyConfiguration{} + err := managedfields.ExtractInto(resourceClass, internal.Parser().Type("io.k8s.api.resource.v1alpha1.ResourceClass"), fieldManager, b, subresource) + if err != nil { + return nil, err + } + b.WithName(resourceClass.Name) + + b.WithKind("ResourceClass") + b.WithAPIVersion("resource.k8s.io/v1alpha1") + return b, nil +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithKind(value string) *ResourceClassApplyConfiguration { + b.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithAPIVersion(value string) *ResourceClassApplyConfiguration { + b.APIVersion = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithName(value string) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithGenerateName(value string) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithNamespace(value string) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithUID(value types.UID) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithResourceVersion(value string) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithGeneration(value int64) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithCreationTimestamp(value metav1.Time) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *ResourceClassApplyConfiguration) WithLabels(entries map[string]string) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Labels == nil && len(entries) > 0 { + b.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *ResourceClassApplyConfiguration) WithAnnotations(entries map[string]string) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Annotations == nil && len(entries) > 0 { + b.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *ResourceClassApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.OwnerReferences = append(b.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *ResourceClassApplyConfiguration) WithFinalizers(values ...string) *ResourceClassApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.Finalizers = append(b.Finalizers, values[i]) + } + return b +} + +func (b *ResourceClassApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{} + } +} + +// WithDriverName sets the DriverName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DriverName field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithDriverName(value string) *ResourceClassApplyConfiguration { + b.DriverName = &value + return b +} + +// WithParametersRef sets the ParametersRef field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ParametersRef field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithParametersRef(value *ResourceClassParametersReferenceApplyConfiguration) *ResourceClassApplyConfiguration { + b.ParametersRef = value + return b +} + +// WithSuitableNodes sets the SuitableNodes field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SuitableNodes field is set to the value of the last call. +func (b *ResourceClassApplyConfiguration) WithSuitableNodes(value *corev1.NodeSelectorApplyConfiguration) *ResourceClassApplyConfiguration { + b.SuitableNodes = value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclassparametersreference.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclassparametersreference.go new file mode 100644 index 00000000000..b03a9a6da4b --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha1/resourceclassparametersreference.go @@ -0,0 +1,66 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +// ResourceClassParametersReferenceApplyConfiguration represents an declarative configuration of the ResourceClassParametersReference type for use +// with apply. +type ResourceClassParametersReferenceApplyConfiguration struct { + APIGroup *string `json:"apiGroup,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` + Namespace *string `json:"namespace,omitempty"` +} + +// ResourceClassParametersReferenceApplyConfiguration constructs an declarative configuration of the ResourceClassParametersReference type for use with +// apply. +func ResourceClassParametersReference() *ResourceClassParametersReferenceApplyConfiguration { + return &ResourceClassParametersReferenceApplyConfiguration{} +} + +// WithAPIGroup sets the APIGroup field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIGroup field is set to the value of the last call. +func (b *ResourceClassParametersReferenceApplyConfiguration) WithAPIGroup(value string) *ResourceClassParametersReferenceApplyConfiguration { + b.APIGroup = &value + return b +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *ResourceClassParametersReferenceApplyConfiguration) WithKind(value string) *ResourceClassParametersReferenceApplyConfiguration { + b.Kind = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *ResourceClassParametersReferenceApplyConfiguration) WithName(value string) *ResourceClassParametersReferenceApplyConfiguration { + b.Name = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *ResourceClassParametersReferenceApplyConfiguration) WithNamespace(value string) *ResourceClassParametersReferenceApplyConfiguration { + b.Namespace = &value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/utils.go b/staging/src/k8s.io/client-go/applyconfigurations/utils.go index a72887b33c6..17d2039254b 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/utils.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/utils.go @@ -58,6 +58,7 @@ import ( rbacv1 "k8s.io/api/rbac/v1" rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" schedulingv1 "k8s.io/api/scheduling/v1" schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" @@ -106,6 +107,7 @@ import ( applyconfigurationsrbacv1 "k8s.io/client-go/applyconfigurations/rbac/v1" applyconfigurationsrbacv1alpha1 "k8s.io/client-go/applyconfigurations/rbac/v1alpha1" applyconfigurationsrbacv1beta1 "k8s.io/client-go/applyconfigurations/rbac/v1beta1" + applyconfigurationsresourcev1alpha1 "k8s.io/client-go/applyconfigurations/resource/v1alpha1" applyconfigurationsschedulingv1 "k8s.io/client-go/applyconfigurations/scheduling/v1" applyconfigurationsschedulingv1alpha1 "k8s.io/client-go/applyconfigurations/scheduling/v1alpha1" applyconfigurationsschedulingv1beta1 "k8s.io/client-go/applyconfigurations/scheduling/v1beta1" @@ -551,6 +553,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &applyconfigurationscorev1.CinderPersistentVolumeSourceApplyConfiguration{} case corev1.SchemeGroupVersion.WithKind("CinderVolumeSource"): return &applyconfigurationscorev1.CinderVolumeSourceApplyConfiguration{} + case corev1.SchemeGroupVersion.WithKind("ClaimSource"): + return &applyconfigurationscorev1.ClaimSourceApplyConfiguration{} case corev1.SchemeGroupVersion.WithKind("ClientIPConfig"): return &applyconfigurationscorev1.ClientIPConfigApplyConfiguration{} case corev1.SchemeGroupVersion.WithKind("ComponentCondition"): @@ -759,6 +763,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &applyconfigurationscorev1.PodOSApplyConfiguration{} case corev1.SchemeGroupVersion.WithKind("PodReadinessGate"): return &applyconfigurationscorev1.PodReadinessGateApplyConfiguration{} + case corev1.SchemeGroupVersion.WithKind("PodResourceClaim"): + return &applyconfigurationscorev1.PodResourceClaimApplyConfiguration{} case corev1.SchemeGroupVersion.WithKind("PodSchedulingGate"): return &applyconfigurationscorev1.PodSchedulingGateApplyConfiguration{} case corev1.SchemeGroupVersion.WithKind("PodSecurityContext"): @@ -797,6 +803,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &applyconfigurationscorev1.ReplicationControllerSpecApplyConfiguration{} case corev1.SchemeGroupVersion.WithKind("ReplicationControllerStatus"): return &applyconfigurationscorev1.ReplicationControllerStatusApplyConfiguration{} + case corev1.SchemeGroupVersion.WithKind("ResourceClaim"): + return &applyconfigurationscorev1.ResourceClaimApplyConfiguration{} case corev1.SchemeGroupVersion.WithKind("ResourceFieldSelector"): return &applyconfigurationscorev1.ResourceFieldSelectorApplyConfiguration{} case corev1.SchemeGroupVersion.WithKind("ResourceQuota"): @@ -1456,6 +1464,36 @@ func ForKind(kind schema.GroupVersionKind) interface{} { case rbacv1beta1.SchemeGroupVersion.WithKind("Subject"): return &applyconfigurationsrbacv1beta1.SubjectApplyConfiguration{} + // Group=resource.k8s.io, Version=v1alpha1 + case resourcev1alpha1.SchemeGroupVersion.WithKind("AllocationResult"): + return &applyconfigurationsresourcev1alpha1.AllocationResultApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("PodScheduling"): + return &applyconfigurationsresourcev1alpha1.PodSchedulingApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("PodSchedulingSpec"): + return &applyconfigurationsresourcev1alpha1.PodSchedulingSpecApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("PodSchedulingStatus"): + return &applyconfigurationsresourcev1alpha1.PodSchedulingStatusApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("ResourceClaim"): + return &applyconfigurationsresourcev1alpha1.ResourceClaimApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("ResourceClaimConsumerReference"): + return &applyconfigurationsresourcev1alpha1.ResourceClaimConsumerReferenceApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("ResourceClaimParametersReference"): + return &applyconfigurationsresourcev1alpha1.ResourceClaimParametersReferenceApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("ResourceClaimSchedulingStatus"): + return &applyconfigurationsresourcev1alpha1.ResourceClaimSchedulingStatusApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("ResourceClaimSpec"): + return &applyconfigurationsresourcev1alpha1.ResourceClaimSpecApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("ResourceClaimStatus"): + return &applyconfigurationsresourcev1alpha1.ResourceClaimStatusApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("ResourceClaimTemplate"): + return &applyconfigurationsresourcev1alpha1.ResourceClaimTemplateApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("ResourceClaimTemplateSpec"): + return &applyconfigurationsresourcev1alpha1.ResourceClaimTemplateSpecApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("ResourceClass"): + return &applyconfigurationsresourcev1alpha1.ResourceClassApplyConfiguration{} + case resourcev1alpha1.SchemeGroupVersion.WithKind("ResourceClassParametersReference"): + return &applyconfigurationsresourcev1alpha1.ResourceClassParametersReferenceApplyConfiguration{} + // Group=scheduling.k8s.io, Version=v1 case schedulingv1.SchemeGroupVersion.WithKind("PriorityClass"): return &applyconfigurationsschedulingv1.PriorityClassApplyConfiguration{} diff --git a/staging/src/k8s.io/client-go/informers/factory.go b/staging/src/k8s.io/client-go/informers/factory.go index 77c3851fc03..8e7a7e36de2 100644 --- a/staging/src/k8s.io/client-go/informers/factory.go +++ b/staging/src/k8s.io/client-go/informers/factory.go @@ -43,6 +43,7 @@ import ( node "k8s.io/client-go/informers/node" policy "k8s.io/client-go/informers/policy" rbac "k8s.io/client-go/informers/rbac" + resource "k8s.io/client-go/informers/resource" scheduling "k8s.io/client-go/informers/scheduling" storage "k8s.io/client-go/informers/storage" kubernetes "k8s.io/client-go/kubernetes" @@ -276,6 +277,7 @@ type SharedInformerFactory interface { Node() node.Interface Policy() policy.Interface Rbac() rbac.Interface + Resource() resource.Interface Scheduling() scheduling.Interface Storage() storage.Interface } @@ -344,6 +346,10 @@ func (f *sharedInformerFactory) Rbac() rbac.Interface { return rbac.New(f, f.namespace, f.tweakListOptions) } +func (f *sharedInformerFactory) Resource() resource.Interface { + return resource.New(f, f.namespace, f.tweakListOptions) +} + func (f *sharedInformerFactory) Scheduling() scheduling.Interface { return scheduling.New(f, f.namespace, f.tweakListOptions) } diff --git a/staging/src/k8s.io/client-go/informers/generic.go b/staging/src/k8s.io/client-go/informers/generic.go index d78c2772e5b..59505bddaa0 100644 --- a/staging/src/k8s.io/client-go/informers/generic.go +++ b/staging/src/k8s.io/client-go/informers/generic.go @@ -59,6 +59,7 @@ import ( rbacv1 "k8s.io/api/rbac/v1" rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" schedulingv1 "k8s.io/api/scheduling/v1" schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" @@ -349,6 +350,16 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource case rbacv1beta1.SchemeGroupVersion.WithResource("rolebindings"): return &genericInformer{resource: resource.GroupResource(), informer: f.Rbac().V1beta1().RoleBindings().Informer()}, nil + // Group=resource.k8s.io, Version=v1alpha1 + case resourcev1alpha1.SchemeGroupVersion.WithResource("podschedulings"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Resource().V1alpha1().PodSchedulings().Informer()}, nil + case resourcev1alpha1.SchemeGroupVersion.WithResource("resourceclaims"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Resource().V1alpha1().ResourceClaims().Informer()}, nil + case resourcev1alpha1.SchemeGroupVersion.WithResource("resourceclaimtemplates"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Resource().V1alpha1().ResourceClaimTemplates().Informer()}, nil + case resourcev1alpha1.SchemeGroupVersion.WithResource("resourceclasses"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Resource().V1alpha1().ResourceClasses().Informer()}, nil + // Group=scheduling.k8s.io, Version=v1 case schedulingv1.SchemeGroupVersion.WithResource("priorityclasses"): return &genericInformer{resource: resource.GroupResource(), informer: f.Scheduling().V1().PriorityClasses().Informer()}, nil diff --git a/staging/src/k8s.io/client-go/informers/resource/interface.go b/staging/src/k8s.io/client-go/informers/resource/interface.go new file mode 100644 index 00000000000..6cf95b0d473 --- /dev/null +++ b/staging/src/k8s.io/client-go/informers/resource/interface.go @@ -0,0 +1,46 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package resource + +import ( + internalinterfaces "k8s.io/client-go/informers/internalinterfaces" + v1alpha1 "k8s.io/client-go/informers/resource/v1alpha1" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/staging/src/k8s.io/client-go/informers/resource/v1alpha1/interface.go b/staging/src/k8s.io/client-go/informers/resource/v1alpha1/interface.go new file mode 100644 index 00000000000..4449dfa652e --- /dev/null +++ b/staging/src/k8s.io/client-go/informers/resource/v1alpha1/interface.go @@ -0,0 +1,66 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + internalinterfaces "k8s.io/client-go/informers/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // PodSchedulings returns a PodSchedulingInformer. + PodSchedulings() PodSchedulingInformer + // ResourceClaims returns a ResourceClaimInformer. + ResourceClaims() ResourceClaimInformer + // ResourceClaimTemplates returns a ResourceClaimTemplateInformer. + ResourceClaimTemplates() ResourceClaimTemplateInformer + // ResourceClasses returns a ResourceClassInformer. + ResourceClasses() ResourceClassInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// PodSchedulings returns a PodSchedulingInformer. +func (v *version) PodSchedulings() PodSchedulingInformer { + return &podSchedulingInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// ResourceClaims returns a ResourceClaimInformer. +func (v *version) ResourceClaims() ResourceClaimInformer { + return &resourceClaimInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// ResourceClaimTemplates returns a ResourceClaimTemplateInformer. +func (v *version) ResourceClaimTemplates() ResourceClaimTemplateInformer { + return &resourceClaimTemplateInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// ResourceClasses returns a ResourceClassInformer. +func (v *version) ResourceClasses() ResourceClassInformer { + return &resourceClassInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/staging/src/k8s.io/client-go/informers/resource/v1alpha1/podscheduling.go b/staging/src/k8s.io/client-go/informers/resource/v1alpha1/podscheduling.go new file mode 100644 index 00000000000..87b4c34e15d --- /dev/null +++ b/staging/src/k8s.io/client-go/informers/resource/v1alpha1/podscheduling.go @@ -0,0 +1,90 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + internalinterfaces "k8s.io/client-go/informers/internalinterfaces" + kubernetes "k8s.io/client-go/kubernetes" + v1alpha1 "k8s.io/client-go/listers/resource/v1alpha1" + cache "k8s.io/client-go/tools/cache" +) + +// PodSchedulingInformer provides access to a shared informer and lister for +// PodSchedulings. +type PodSchedulingInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.PodSchedulingLister +} + +type podSchedulingInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewPodSchedulingInformer constructs a new informer for PodScheduling type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewPodSchedulingInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredPodSchedulingInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredPodSchedulingInformer constructs a new informer for PodScheduling type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredPodSchedulingInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ResourceV1alpha1().PodSchedulings(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ResourceV1alpha1().PodSchedulings(namespace).Watch(context.TODO(), options) + }, + }, + &resourcev1alpha1.PodScheduling{}, + resyncPeriod, + indexers, + ) +} + +func (f *podSchedulingInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredPodSchedulingInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *podSchedulingInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&resourcev1alpha1.PodScheduling{}, f.defaultInformer) +} + +func (f *podSchedulingInformer) Lister() v1alpha1.PodSchedulingLister { + return v1alpha1.NewPodSchedulingLister(f.Informer().GetIndexer()) +} diff --git a/staging/src/k8s.io/client-go/informers/resource/v1alpha1/resourceclaim.go b/staging/src/k8s.io/client-go/informers/resource/v1alpha1/resourceclaim.go new file mode 100644 index 00000000000..10150c02078 --- /dev/null +++ b/staging/src/k8s.io/client-go/informers/resource/v1alpha1/resourceclaim.go @@ -0,0 +1,90 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + internalinterfaces "k8s.io/client-go/informers/internalinterfaces" + kubernetes "k8s.io/client-go/kubernetes" + v1alpha1 "k8s.io/client-go/listers/resource/v1alpha1" + cache "k8s.io/client-go/tools/cache" +) + +// ResourceClaimInformer provides access to a shared informer and lister for +// ResourceClaims. +type ResourceClaimInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ResourceClaimLister +} + +type resourceClaimInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewResourceClaimInformer constructs a new informer for ResourceClaim type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewResourceClaimInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredResourceClaimInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredResourceClaimInformer constructs a new informer for ResourceClaim type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredResourceClaimInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ResourceV1alpha1().ResourceClaims(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ResourceV1alpha1().ResourceClaims(namespace).Watch(context.TODO(), options) + }, + }, + &resourcev1alpha1.ResourceClaim{}, + resyncPeriod, + indexers, + ) +} + +func (f *resourceClaimInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredResourceClaimInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *resourceClaimInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&resourcev1alpha1.ResourceClaim{}, f.defaultInformer) +} + +func (f *resourceClaimInformer) Lister() v1alpha1.ResourceClaimLister { + return v1alpha1.NewResourceClaimLister(f.Informer().GetIndexer()) +} diff --git a/staging/src/k8s.io/client-go/informers/resource/v1alpha1/resourceclaimtemplate.go b/staging/src/k8s.io/client-go/informers/resource/v1alpha1/resourceclaimtemplate.go new file mode 100644 index 00000000000..cdffa49db7f --- /dev/null +++ b/staging/src/k8s.io/client-go/informers/resource/v1alpha1/resourceclaimtemplate.go @@ -0,0 +1,90 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + internalinterfaces "k8s.io/client-go/informers/internalinterfaces" + kubernetes "k8s.io/client-go/kubernetes" + v1alpha1 "k8s.io/client-go/listers/resource/v1alpha1" + cache "k8s.io/client-go/tools/cache" +) + +// ResourceClaimTemplateInformer provides access to a shared informer and lister for +// ResourceClaimTemplates. +type ResourceClaimTemplateInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ResourceClaimTemplateLister +} + +type resourceClaimTemplateInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewResourceClaimTemplateInformer constructs a new informer for ResourceClaimTemplate type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewResourceClaimTemplateInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredResourceClaimTemplateInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredResourceClaimTemplateInformer constructs a new informer for ResourceClaimTemplate type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredResourceClaimTemplateInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ResourceV1alpha1().ResourceClaimTemplates(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ResourceV1alpha1().ResourceClaimTemplates(namespace).Watch(context.TODO(), options) + }, + }, + &resourcev1alpha1.ResourceClaimTemplate{}, + resyncPeriod, + indexers, + ) +} + +func (f *resourceClaimTemplateInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredResourceClaimTemplateInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *resourceClaimTemplateInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&resourcev1alpha1.ResourceClaimTemplate{}, f.defaultInformer) +} + +func (f *resourceClaimTemplateInformer) Lister() v1alpha1.ResourceClaimTemplateLister { + return v1alpha1.NewResourceClaimTemplateLister(f.Informer().GetIndexer()) +} diff --git a/staging/src/k8s.io/client-go/informers/resource/v1alpha1/resourceclass.go b/staging/src/k8s.io/client-go/informers/resource/v1alpha1/resourceclass.go new file mode 100644 index 00000000000..e6faa5d02ea --- /dev/null +++ b/staging/src/k8s.io/client-go/informers/resource/v1alpha1/resourceclass.go @@ -0,0 +1,89 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + internalinterfaces "k8s.io/client-go/informers/internalinterfaces" + kubernetes "k8s.io/client-go/kubernetes" + v1alpha1 "k8s.io/client-go/listers/resource/v1alpha1" + cache "k8s.io/client-go/tools/cache" +) + +// ResourceClassInformer provides access to a shared informer and lister for +// ResourceClasses. +type ResourceClassInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ResourceClassLister +} + +type resourceClassInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewResourceClassInformer constructs a new informer for ResourceClass type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewResourceClassInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredResourceClassInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredResourceClassInformer constructs a new informer for ResourceClass type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredResourceClassInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ResourceV1alpha1().ResourceClasses().List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ResourceV1alpha1().ResourceClasses().Watch(context.TODO(), options) + }, + }, + &resourcev1alpha1.ResourceClass{}, + resyncPeriod, + indexers, + ) +} + +func (f *resourceClassInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredResourceClassInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *resourceClassInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&resourcev1alpha1.ResourceClass{}, f.defaultInformer) +} + +func (f *resourceClassInformer) Lister() v1alpha1.ResourceClassLister { + return v1alpha1.NewResourceClassLister(f.Informer().GetIndexer()) +} diff --git a/staging/src/k8s.io/client-go/kubernetes/clientset.go b/staging/src/k8s.io/client-go/kubernetes/clientset.go index 5572d219fc3..9eecbb2a805 100644 --- a/staging/src/k8s.io/client-go/kubernetes/clientset.go +++ b/staging/src/k8s.io/client-go/kubernetes/clientset.go @@ -66,6 +66,7 @@ import ( rbacv1 "k8s.io/client-go/kubernetes/typed/rbac/v1" rbacv1alpha1 "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1" rbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1" + resourcev1alpha1 "k8s.io/client-go/kubernetes/typed/resource/v1alpha1" schedulingv1 "k8s.io/client-go/kubernetes/typed/scheduling/v1" schedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1" schedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1" @@ -121,6 +122,7 @@ type Interface interface { RbacV1() rbacv1.RbacV1Interface RbacV1beta1() rbacv1beta1.RbacV1beta1Interface RbacV1alpha1() rbacv1alpha1.RbacV1alpha1Interface + ResourceV1alpha1() resourcev1alpha1.ResourceV1alpha1Interface SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface SchedulingV1() schedulingv1.SchedulingV1Interface @@ -175,6 +177,7 @@ type Clientset struct { rbacV1 *rbacv1.RbacV1Client rbacV1beta1 *rbacv1beta1.RbacV1beta1Client rbacV1alpha1 *rbacv1alpha1.RbacV1alpha1Client + resourceV1alpha1 *resourcev1alpha1.ResourceV1alpha1Client schedulingV1alpha1 *schedulingv1alpha1.SchedulingV1alpha1Client schedulingV1beta1 *schedulingv1beta1.SchedulingV1beta1Client schedulingV1 *schedulingv1.SchedulingV1Client @@ -398,6 +401,11 @@ func (c *Clientset) RbacV1alpha1() rbacv1alpha1.RbacV1alpha1Interface { return c.rbacV1alpha1 } +// ResourceV1alpha1 retrieves the ResourceV1alpha1Client +func (c *Clientset) ResourceV1alpha1() resourcev1alpha1.ResourceV1alpha1Interface { + return c.resourceV1alpha1 +} + // SchedulingV1alpha1 retrieves the SchedulingV1alpha1Client func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface { return c.schedulingV1alpha1 @@ -644,6 +652,10 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, if err != nil { return nil, err } + cs.resourceV1alpha1, err = resourcev1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } cs.schedulingV1alpha1, err = schedulingv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) if err != nil { return nil, err @@ -732,6 +744,7 @@ func New(c rest.Interface) *Clientset { cs.rbacV1 = rbacv1.New(c) cs.rbacV1beta1 = rbacv1beta1.New(c) cs.rbacV1alpha1 = rbacv1alpha1.New(c) + cs.resourceV1alpha1 = resourcev1alpha1.New(c) cs.schedulingV1alpha1 = schedulingv1alpha1.New(c) cs.schedulingV1beta1 = schedulingv1beta1.New(c) cs.schedulingV1 = schedulingv1.New(c) diff --git a/staging/src/k8s.io/client-go/kubernetes/fake/clientset_generated.go b/staging/src/k8s.io/client-go/kubernetes/fake/clientset_generated.go index d9cd1ae3d16..f4d621941e9 100644 --- a/staging/src/k8s.io/client-go/kubernetes/fake/clientset_generated.go +++ b/staging/src/k8s.io/client-go/kubernetes/fake/clientset_generated.go @@ -110,6 +110,8 @@ import ( fakerbacv1alpha1 "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake" rbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1" fakerbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake" + resourcev1alpha1 "k8s.io/client-go/kubernetes/typed/resource/v1alpha1" + fakeresourcev1alpha1 "k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake" schedulingv1 "k8s.io/client-go/kubernetes/typed/scheduling/v1" fakeschedulingv1 "k8s.io/client-go/kubernetes/typed/scheduling/v1/fake" schedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1" @@ -390,6 +392,11 @@ func (c *Clientset) RbacV1alpha1() rbacv1alpha1.RbacV1alpha1Interface { return &fakerbacv1alpha1.FakeRbacV1alpha1{Fake: &c.Fake} } +// ResourceV1alpha1 retrieves the ResourceV1alpha1Client +func (c *Clientset) ResourceV1alpha1() resourcev1alpha1.ResourceV1alpha1Interface { + return &fakeresourcev1alpha1.FakeResourceV1alpha1{Fake: &c.Fake} +} + // SchedulingV1alpha1 retrieves the SchedulingV1alpha1Client func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface { return &fakeschedulingv1alpha1.FakeSchedulingV1alpha1{Fake: &c.Fake} diff --git a/staging/src/k8s.io/client-go/kubernetes/fake/register.go b/staging/src/k8s.io/client-go/kubernetes/fake/register.go index 92c177a4843..30f42e25dae 100644 --- a/staging/src/k8s.io/client-go/kubernetes/fake/register.go +++ b/staging/src/k8s.io/client-go/kubernetes/fake/register.go @@ -62,6 +62,7 @@ import ( rbacv1 "k8s.io/api/rbac/v1" rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" schedulingv1 "k8s.io/api/scheduling/v1" schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" @@ -122,6 +123,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{ rbacv1.AddToScheme, rbacv1beta1.AddToScheme, rbacv1alpha1.AddToScheme, + resourcev1alpha1.AddToScheme, schedulingv1alpha1.AddToScheme, schedulingv1beta1.AddToScheme, schedulingv1.AddToScheme, diff --git a/staging/src/k8s.io/client-go/kubernetes/scheme/register.go b/staging/src/k8s.io/client-go/kubernetes/scheme/register.go index 73595b655b7..e43780529b2 100644 --- a/staging/src/k8s.io/client-go/kubernetes/scheme/register.go +++ b/staging/src/k8s.io/client-go/kubernetes/scheme/register.go @@ -62,6 +62,7 @@ import ( rbacv1 "k8s.io/api/rbac/v1" rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" schedulingv1 "k8s.io/api/scheduling/v1" schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" @@ -122,6 +123,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{ rbacv1.AddToScheme, rbacv1beta1.AddToScheme, rbacv1alpha1.AddToScheme, + resourcev1alpha1.AddToScheme, schedulingv1alpha1.AddToScheme, schedulingv1beta1.AddToScheme, schedulingv1.AddToScheme, diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/doc.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/doc.go new file mode 100644 index 00000000000..df51baa4d4c --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/doc.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/doc.go new file mode 100644 index 00000000000..16f44399065 --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_podscheduling.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_podscheduling.go new file mode 100644 index 00000000000..7b4e2a5d5a4 --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_podscheduling.go @@ -0,0 +1,190 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + json "encoding/json" + "fmt" + + v1alpha1 "k8s.io/api/resource/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + resourcev1alpha1 "k8s.io/client-go/applyconfigurations/resource/v1alpha1" + testing "k8s.io/client-go/testing" +) + +// FakePodSchedulings implements PodSchedulingInterface +type FakePodSchedulings struct { + Fake *FakeResourceV1alpha1 + ns string +} + +var podschedulingsResource = schema.GroupVersionResource{Group: "resource.k8s.io", Version: "v1alpha1", Resource: "podschedulings"} + +var podschedulingsKind = schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha1", Kind: "PodScheduling"} + +// Get takes name of the podScheduling, and returns the corresponding podScheduling object, and an error if there is any. +func (c *FakePodSchedulings) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PodScheduling, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(podschedulingsResource, c.ns, name), &v1alpha1.PodScheduling{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PodScheduling), err +} + +// List takes label and field selectors, and returns the list of PodSchedulings that match those selectors. +func (c *FakePodSchedulings) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PodSchedulingList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(podschedulingsResource, podschedulingsKind, c.ns, opts), &v1alpha1.PodSchedulingList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.PodSchedulingList{ListMeta: obj.(*v1alpha1.PodSchedulingList).ListMeta} + for _, item := range obj.(*v1alpha1.PodSchedulingList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested podSchedulings. +func (c *FakePodSchedulings) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(podschedulingsResource, c.ns, opts)) + +} + +// Create takes the representation of a podScheduling and creates it. Returns the server's representation of the podScheduling, and an error, if there is any. +func (c *FakePodSchedulings) Create(ctx context.Context, podScheduling *v1alpha1.PodScheduling, opts v1.CreateOptions) (result *v1alpha1.PodScheduling, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(podschedulingsResource, c.ns, podScheduling), &v1alpha1.PodScheduling{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PodScheduling), err +} + +// Update takes the representation of a podScheduling and updates it. Returns the server's representation of the podScheduling, and an error, if there is any. +func (c *FakePodSchedulings) Update(ctx context.Context, podScheduling *v1alpha1.PodScheduling, opts v1.UpdateOptions) (result *v1alpha1.PodScheduling, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(podschedulingsResource, c.ns, podScheduling), &v1alpha1.PodScheduling{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PodScheduling), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakePodSchedulings) UpdateStatus(ctx context.Context, podScheduling *v1alpha1.PodScheduling, opts v1.UpdateOptions) (*v1alpha1.PodScheduling, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(podschedulingsResource, "status", c.ns, podScheduling), &v1alpha1.PodScheduling{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PodScheduling), err +} + +// Delete takes name of the podScheduling and deletes it. Returns an error if one occurs. +func (c *FakePodSchedulings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(podschedulingsResource, c.ns, name, opts), &v1alpha1.PodScheduling{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakePodSchedulings) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(podschedulingsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.PodSchedulingList{}) + return err +} + +// Patch applies the patch and returns the patched podScheduling. +func (c *FakePodSchedulings) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PodScheduling, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(podschedulingsResource, c.ns, name, pt, data, subresources...), &v1alpha1.PodScheduling{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PodScheduling), err +} + +// Apply takes the given apply declarative configuration, applies it and returns the applied podScheduling. +func (c *FakePodSchedulings) Apply(ctx context.Context, podScheduling *resourcev1alpha1.PodSchedulingApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.PodScheduling, err error) { + if podScheduling == nil { + return nil, fmt.Errorf("podScheduling provided to Apply must not be nil") + } + data, err := json.Marshal(podScheduling) + if err != nil { + return nil, err + } + name := podScheduling.Name + if name == nil { + return nil, fmt.Errorf("podScheduling.Name must be provided to Apply") + } + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(podschedulingsResource, c.ns, *name, types.ApplyPatchType, data), &v1alpha1.PodScheduling{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PodScheduling), err +} + +// ApplyStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). +func (c *FakePodSchedulings) ApplyStatus(ctx context.Context, podScheduling *resourcev1alpha1.PodSchedulingApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.PodScheduling, err error) { + if podScheduling == nil { + return nil, fmt.Errorf("podScheduling provided to Apply must not be nil") + } + data, err := json.Marshal(podScheduling) + if err != nil { + return nil, err + } + name := podScheduling.Name + if name == nil { + return nil, fmt.Errorf("podScheduling.Name must be provided to Apply") + } + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(podschedulingsResource, c.ns, *name, types.ApplyPatchType, data, "status"), &v1alpha1.PodScheduling{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PodScheduling), err +} diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_resource_client.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_resource_client.go new file mode 100644 index 00000000000..c4776ee54f4 --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_resource_client.go @@ -0,0 +1,52 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "k8s.io/client-go/kubernetes/typed/resource/v1alpha1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeResourceV1alpha1 struct { + *testing.Fake +} + +func (c *FakeResourceV1alpha1) PodSchedulings(namespace string) v1alpha1.PodSchedulingInterface { + return &FakePodSchedulings{c, namespace} +} + +func (c *FakeResourceV1alpha1) ResourceClaims(namespace string) v1alpha1.ResourceClaimInterface { + return &FakeResourceClaims{c, namespace} +} + +func (c *FakeResourceV1alpha1) ResourceClaimTemplates(namespace string) v1alpha1.ResourceClaimTemplateInterface { + return &FakeResourceClaimTemplates{c, namespace} +} + +func (c *FakeResourceV1alpha1) ResourceClasses() v1alpha1.ResourceClassInterface { + return &FakeResourceClasses{c} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeResourceV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_resourceclaim.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_resourceclaim.go new file mode 100644 index 00000000000..a458459f84f --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_resourceclaim.go @@ -0,0 +1,190 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + json "encoding/json" + "fmt" + + v1alpha1 "k8s.io/api/resource/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + resourcev1alpha1 "k8s.io/client-go/applyconfigurations/resource/v1alpha1" + testing "k8s.io/client-go/testing" +) + +// FakeResourceClaims implements ResourceClaimInterface +type FakeResourceClaims struct { + Fake *FakeResourceV1alpha1 + ns string +} + +var resourceclaimsResource = schema.GroupVersionResource{Group: "resource.k8s.io", Version: "v1alpha1", Resource: "resourceclaims"} + +var resourceclaimsKind = schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha1", Kind: "ResourceClaim"} + +// Get takes name of the resourceClaim, and returns the corresponding resourceClaim object, and an error if there is any. +func (c *FakeResourceClaims) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ResourceClaim, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(resourceclaimsResource, c.ns, name), &v1alpha1.ResourceClaim{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClaim), err +} + +// List takes label and field selectors, and returns the list of ResourceClaims that match those selectors. +func (c *FakeResourceClaims) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ResourceClaimList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(resourceclaimsResource, resourceclaimsKind, c.ns, opts), &v1alpha1.ResourceClaimList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.ResourceClaimList{ListMeta: obj.(*v1alpha1.ResourceClaimList).ListMeta} + for _, item := range obj.(*v1alpha1.ResourceClaimList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested resourceClaims. +func (c *FakeResourceClaims) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(resourceclaimsResource, c.ns, opts)) + +} + +// Create takes the representation of a resourceClaim and creates it. Returns the server's representation of the resourceClaim, and an error, if there is any. +func (c *FakeResourceClaims) Create(ctx context.Context, resourceClaim *v1alpha1.ResourceClaim, opts v1.CreateOptions) (result *v1alpha1.ResourceClaim, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(resourceclaimsResource, c.ns, resourceClaim), &v1alpha1.ResourceClaim{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClaim), err +} + +// Update takes the representation of a resourceClaim and updates it. Returns the server's representation of the resourceClaim, and an error, if there is any. +func (c *FakeResourceClaims) Update(ctx context.Context, resourceClaim *v1alpha1.ResourceClaim, opts v1.UpdateOptions) (result *v1alpha1.ResourceClaim, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(resourceclaimsResource, c.ns, resourceClaim), &v1alpha1.ResourceClaim{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClaim), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeResourceClaims) UpdateStatus(ctx context.Context, resourceClaim *v1alpha1.ResourceClaim, opts v1.UpdateOptions) (*v1alpha1.ResourceClaim, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(resourceclaimsResource, "status", c.ns, resourceClaim), &v1alpha1.ResourceClaim{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClaim), err +} + +// Delete takes name of the resourceClaim and deletes it. Returns an error if one occurs. +func (c *FakeResourceClaims) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(resourceclaimsResource, c.ns, name, opts), &v1alpha1.ResourceClaim{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeResourceClaims) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(resourceclaimsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.ResourceClaimList{}) + return err +} + +// Patch applies the patch and returns the patched resourceClaim. +func (c *FakeResourceClaims) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceClaim, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(resourceclaimsResource, c.ns, name, pt, data, subresources...), &v1alpha1.ResourceClaim{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClaim), err +} + +// Apply takes the given apply declarative configuration, applies it and returns the applied resourceClaim. +func (c *FakeResourceClaims) Apply(ctx context.Context, resourceClaim *resourcev1alpha1.ResourceClaimApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ResourceClaim, err error) { + if resourceClaim == nil { + return nil, fmt.Errorf("resourceClaim provided to Apply must not be nil") + } + data, err := json.Marshal(resourceClaim) + if err != nil { + return nil, err + } + name := resourceClaim.Name + if name == nil { + return nil, fmt.Errorf("resourceClaim.Name must be provided to Apply") + } + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(resourceclaimsResource, c.ns, *name, types.ApplyPatchType, data), &v1alpha1.ResourceClaim{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClaim), err +} + +// ApplyStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). +func (c *FakeResourceClaims) ApplyStatus(ctx context.Context, resourceClaim *resourcev1alpha1.ResourceClaimApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ResourceClaim, err error) { + if resourceClaim == nil { + return nil, fmt.Errorf("resourceClaim provided to Apply must not be nil") + } + data, err := json.Marshal(resourceClaim) + if err != nil { + return nil, err + } + name := resourceClaim.Name + if name == nil { + return nil, fmt.Errorf("resourceClaim.Name must be provided to Apply") + } + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(resourceclaimsResource, c.ns, *name, types.ApplyPatchType, data, "status"), &v1alpha1.ResourceClaim{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClaim), err +} diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_resourceclaimtemplate.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_resourceclaimtemplate.go new file mode 100644 index 00000000000..be22ab6d370 --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_resourceclaimtemplate.go @@ -0,0 +1,155 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + json "encoding/json" + "fmt" + + v1alpha1 "k8s.io/api/resource/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + resourcev1alpha1 "k8s.io/client-go/applyconfigurations/resource/v1alpha1" + testing "k8s.io/client-go/testing" +) + +// FakeResourceClaimTemplates implements ResourceClaimTemplateInterface +type FakeResourceClaimTemplates struct { + Fake *FakeResourceV1alpha1 + ns string +} + +var resourceclaimtemplatesResource = schema.GroupVersionResource{Group: "resource.k8s.io", Version: "v1alpha1", Resource: "resourceclaimtemplates"} + +var resourceclaimtemplatesKind = schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha1", Kind: "ResourceClaimTemplate"} + +// Get takes name of the resourceClaimTemplate, and returns the corresponding resourceClaimTemplate object, and an error if there is any. +func (c *FakeResourceClaimTemplates) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ResourceClaimTemplate, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(resourceclaimtemplatesResource, c.ns, name), &v1alpha1.ResourceClaimTemplate{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClaimTemplate), err +} + +// List takes label and field selectors, and returns the list of ResourceClaimTemplates that match those selectors. +func (c *FakeResourceClaimTemplates) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ResourceClaimTemplateList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(resourceclaimtemplatesResource, resourceclaimtemplatesKind, c.ns, opts), &v1alpha1.ResourceClaimTemplateList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.ResourceClaimTemplateList{ListMeta: obj.(*v1alpha1.ResourceClaimTemplateList).ListMeta} + for _, item := range obj.(*v1alpha1.ResourceClaimTemplateList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested resourceClaimTemplates. +func (c *FakeResourceClaimTemplates) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(resourceclaimtemplatesResource, c.ns, opts)) + +} + +// Create takes the representation of a resourceClaimTemplate and creates it. Returns the server's representation of the resourceClaimTemplate, and an error, if there is any. +func (c *FakeResourceClaimTemplates) Create(ctx context.Context, resourceClaimTemplate *v1alpha1.ResourceClaimTemplate, opts v1.CreateOptions) (result *v1alpha1.ResourceClaimTemplate, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(resourceclaimtemplatesResource, c.ns, resourceClaimTemplate), &v1alpha1.ResourceClaimTemplate{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClaimTemplate), err +} + +// Update takes the representation of a resourceClaimTemplate and updates it. Returns the server's representation of the resourceClaimTemplate, and an error, if there is any. +func (c *FakeResourceClaimTemplates) Update(ctx context.Context, resourceClaimTemplate *v1alpha1.ResourceClaimTemplate, opts v1.UpdateOptions) (result *v1alpha1.ResourceClaimTemplate, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(resourceclaimtemplatesResource, c.ns, resourceClaimTemplate), &v1alpha1.ResourceClaimTemplate{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClaimTemplate), err +} + +// Delete takes name of the resourceClaimTemplate and deletes it. Returns an error if one occurs. +func (c *FakeResourceClaimTemplates) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(resourceclaimtemplatesResource, c.ns, name, opts), &v1alpha1.ResourceClaimTemplate{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeResourceClaimTemplates) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(resourceclaimtemplatesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.ResourceClaimTemplateList{}) + return err +} + +// Patch applies the patch and returns the patched resourceClaimTemplate. +func (c *FakeResourceClaimTemplates) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceClaimTemplate, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(resourceclaimtemplatesResource, c.ns, name, pt, data, subresources...), &v1alpha1.ResourceClaimTemplate{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClaimTemplate), err +} + +// Apply takes the given apply declarative configuration, applies it and returns the applied resourceClaimTemplate. +func (c *FakeResourceClaimTemplates) Apply(ctx context.Context, resourceClaimTemplate *resourcev1alpha1.ResourceClaimTemplateApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ResourceClaimTemplate, err error) { + if resourceClaimTemplate == nil { + return nil, fmt.Errorf("resourceClaimTemplate provided to Apply must not be nil") + } + data, err := json.Marshal(resourceClaimTemplate) + if err != nil { + return nil, err + } + name := resourceClaimTemplate.Name + if name == nil { + return nil, fmt.Errorf("resourceClaimTemplate.Name must be provided to Apply") + } + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(resourceclaimtemplatesResource, c.ns, *name, types.ApplyPatchType, data), &v1alpha1.ResourceClaimTemplate{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClaimTemplate), err +} diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_resourceclass.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_resourceclass.go new file mode 100644 index 00000000000..80fb7ec034b --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake/fake_resourceclass.go @@ -0,0 +1,146 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + json "encoding/json" + "fmt" + + v1alpha1 "k8s.io/api/resource/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + resourcev1alpha1 "k8s.io/client-go/applyconfigurations/resource/v1alpha1" + testing "k8s.io/client-go/testing" +) + +// FakeResourceClasses implements ResourceClassInterface +type FakeResourceClasses struct { + Fake *FakeResourceV1alpha1 +} + +var resourceclassesResource = schema.GroupVersionResource{Group: "resource.k8s.io", Version: "v1alpha1", Resource: "resourceclasses"} + +var resourceclassesKind = schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha1", Kind: "ResourceClass"} + +// Get takes name of the resourceClass, and returns the corresponding resourceClass object, and an error if there is any. +func (c *FakeResourceClasses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ResourceClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(resourceclassesResource, name), &v1alpha1.ResourceClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClass), err +} + +// List takes label and field selectors, and returns the list of ResourceClasses that match those selectors. +func (c *FakeResourceClasses) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ResourceClassList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(resourceclassesResource, resourceclassesKind, opts), &v1alpha1.ResourceClassList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.ResourceClassList{ListMeta: obj.(*v1alpha1.ResourceClassList).ListMeta} + for _, item := range obj.(*v1alpha1.ResourceClassList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested resourceClasses. +func (c *FakeResourceClasses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(resourceclassesResource, opts)) +} + +// Create takes the representation of a resourceClass and creates it. Returns the server's representation of the resourceClass, and an error, if there is any. +func (c *FakeResourceClasses) Create(ctx context.Context, resourceClass *v1alpha1.ResourceClass, opts v1.CreateOptions) (result *v1alpha1.ResourceClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(resourceclassesResource, resourceClass), &v1alpha1.ResourceClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClass), err +} + +// Update takes the representation of a resourceClass and updates it. Returns the server's representation of the resourceClass, and an error, if there is any. +func (c *FakeResourceClasses) Update(ctx context.Context, resourceClass *v1alpha1.ResourceClass, opts v1.UpdateOptions) (result *v1alpha1.ResourceClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(resourceclassesResource, resourceClass), &v1alpha1.ResourceClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClass), err +} + +// Delete takes name of the resourceClass and deletes it. Returns an error if one occurs. +func (c *FakeResourceClasses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteActionWithOptions(resourceclassesResource, name, opts), &v1alpha1.ResourceClass{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeResourceClasses) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(resourceclassesResource, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.ResourceClassList{}) + return err +} + +// Patch applies the patch and returns the patched resourceClass. +func (c *FakeResourceClasses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(resourceclassesResource, name, pt, data, subresources...), &v1alpha1.ResourceClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClass), err +} + +// Apply takes the given apply declarative configuration, applies it and returns the applied resourceClass. +func (c *FakeResourceClasses) Apply(ctx context.Context, resourceClass *resourcev1alpha1.ResourceClassApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ResourceClass, err error) { + if resourceClass == nil { + return nil, fmt.Errorf("resourceClass provided to Apply must not be nil") + } + data, err := json.Marshal(resourceClass) + if err != nil { + return nil, err + } + name := resourceClass.Name + if name == nil { + return nil, fmt.Errorf("resourceClass.Name must be provided to Apply") + } + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(resourceclassesResource, *name, types.ApplyPatchType, data), &v1alpha1.ResourceClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ResourceClass), err +} diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/generated_expansion.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/generated_expansion.go new file mode 100644 index 00000000000..df88c2f93be --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/generated_expansion.go @@ -0,0 +1,27 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type PodSchedulingExpansion interface{} + +type ResourceClaimExpansion interface{} + +type ResourceClaimTemplateExpansion interface{} + +type ResourceClassExpansion interface{} diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/podscheduling.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/podscheduling.go new file mode 100644 index 00000000000..e163a845615 --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/podscheduling.go @@ -0,0 +1,256 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + json "encoding/json" + "fmt" + "time" + + v1alpha1 "k8s.io/api/resource/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + resourcev1alpha1 "k8s.io/client-go/applyconfigurations/resource/v1alpha1" + scheme "k8s.io/client-go/kubernetes/scheme" + rest "k8s.io/client-go/rest" +) + +// PodSchedulingsGetter has a method to return a PodSchedulingInterface. +// A group's client should implement this interface. +type PodSchedulingsGetter interface { + PodSchedulings(namespace string) PodSchedulingInterface +} + +// PodSchedulingInterface has methods to work with PodScheduling resources. +type PodSchedulingInterface interface { + Create(ctx context.Context, podScheduling *v1alpha1.PodScheduling, opts v1.CreateOptions) (*v1alpha1.PodScheduling, error) + Update(ctx context.Context, podScheduling *v1alpha1.PodScheduling, opts v1.UpdateOptions) (*v1alpha1.PodScheduling, error) + UpdateStatus(ctx context.Context, podScheduling *v1alpha1.PodScheduling, opts v1.UpdateOptions) (*v1alpha1.PodScheduling, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.PodScheduling, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.PodSchedulingList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PodScheduling, err error) + Apply(ctx context.Context, podScheduling *resourcev1alpha1.PodSchedulingApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.PodScheduling, err error) + ApplyStatus(ctx context.Context, podScheduling *resourcev1alpha1.PodSchedulingApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.PodScheduling, err error) + PodSchedulingExpansion +} + +// podSchedulings implements PodSchedulingInterface +type podSchedulings struct { + client rest.Interface + ns string +} + +// newPodSchedulings returns a PodSchedulings +func newPodSchedulings(c *ResourceV1alpha1Client, namespace string) *podSchedulings { + return &podSchedulings{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the podScheduling, and returns the corresponding podScheduling object, and an error if there is any. +func (c *podSchedulings) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PodScheduling, err error) { + result = &v1alpha1.PodScheduling{} + err = c.client.Get(). + Namespace(c.ns). + Resource("podschedulings"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of PodSchedulings that match those selectors. +func (c *podSchedulings) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PodSchedulingList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.PodSchedulingList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("podschedulings"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested podSchedulings. +func (c *podSchedulings) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("podschedulings"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a podScheduling and creates it. Returns the server's representation of the podScheduling, and an error, if there is any. +func (c *podSchedulings) Create(ctx context.Context, podScheduling *v1alpha1.PodScheduling, opts v1.CreateOptions) (result *v1alpha1.PodScheduling, err error) { + result = &v1alpha1.PodScheduling{} + err = c.client.Post(). + Namespace(c.ns). + Resource("podschedulings"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(podScheduling). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a podScheduling and updates it. Returns the server's representation of the podScheduling, and an error, if there is any. +func (c *podSchedulings) Update(ctx context.Context, podScheduling *v1alpha1.PodScheduling, opts v1.UpdateOptions) (result *v1alpha1.PodScheduling, err error) { + result = &v1alpha1.PodScheduling{} + err = c.client.Put(). + Namespace(c.ns). + Resource("podschedulings"). + Name(podScheduling.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(podScheduling). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *podSchedulings) UpdateStatus(ctx context.Context, podScheduling *v1alpha1.PodScheduling, opts v1.UpdateOptions) (result *v1alpha1.PodScheduling, err error) { + result = &v1alpha1.PodScheduling{} + err = c.client.Put(). + Namespace(c.ns). + Resource("podschedulings"). + Name(podScheduling.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(podScheduling). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the podScheduling and deletes it. Returns an error if one occurs. +func (c *podSchedulings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("podschedulings"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *podSchedulings) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("podschedulings"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched podScheduling. +func (c *podSchedulings) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PodScheduling, err error) { + result = &v1alpha1.PodScheduling{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("podschedulings"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} + +// Apply takes the given apply declarative configuration, applies it and returns the applied podScheduling. +func (c *podSchedulings) Apply(ctx context.Context, podScheduling *resourcev1alpha1.PodSchedulingApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.PodScheduling, err error) { + if podScheduling == nil { + return nil, fmt.Errorf("podScheduling provided to Apply must not be nil") + } + patchOpts := opts.ToPatchOptions() + data, err := json.Marshal(podScheduling) + if err != nil { + return nil, err + } + name := podScheduling.Name + if name == nil { + return nil, fmt.Errorf("podScheduling.Name must be provided to Apply") + } + result = &v1alpha1.PodScheduling{} + err = c.client.Patch(types.ApplyPatchType). + Namespace(c.ns). + Resource("podschedulings"). + Name(*name). + VersionedParams(&patchOpts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} + +// ApplyStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). +func (c *podSchedulings) ApplyStatus(ctx context.Context, podScheduling *resourcev1alpha1.PodSchedulingApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.PodScheduling, err error) { + if podScheduling == nil { + return nil, fmt.Errorf("podScheduling provided to Apply must not be nil") + } + patchOpts := opts.ToPatchOptions() + data, err := json.Marshal(podScheduling) + if err != nil { + return nil, err + } + + name := podScheduling.Name + if name == nil { + return nil, fmt.Errorf("podScheduling.Name must be provided to Apply") + } + + result = &v1alpha1.PodScheduling{} + err = c.client.Patch(types.ApplyPatchType). + Namespace(c.ns). + Resource("podschedulings"). + Name(*name). + SubResource("status"). + VersionedParams(&patchOpts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/resource_client.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/resource_client.go new file mode 100644 index 00000000000..2355bf7ccbe --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/resource_client.go @@ -0,0 +1,122 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "net/http" + + v1alpha1 "k8s.io/api/resource/v1alpha1" + "k8s.io/client-go/kubernetes/scheme" + rest "k8s.io/client-go/rest" +) + +type ResourceV1alpha1Interface interface { + RESTClient() rest.Interface + PodSchedulingsGetter + ResourceClaimsGetter + ResourceClaimTemplatesGetter + ResourceClassesGetter +} + +// ResourceV1alpha1Client is used to interact with features provided by the resource.k8s.io group. +type ResourceV1alpha1Client struct { + restClient rest.Interface +} + +func (c *ResourceV1alpha1Client) PodSchedulings(namespace string) PodSchedulingInterface { + return newPodSchedulings(c, namespace) +} + +func (c *ResourceV1alpha1Client) ResourceClaims(namespace string) ResourceClaimInterface { + return newResourceClaims(c, namespace) +} + +func (c *ResourceV1alpha1Client) ResourceClaimTemplates(namespace string) ResourceClaimTemplateInterface { + return newResourceClaimTemplates(c, namespace) +} + +func (c *ResourceV1alpha1Client) ResourceClasses() ResourceClassInterface { + return newResourceClasses(c) +} + +// NewForConfig creates a new ResourceV1alpha1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*ResourceV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new ResourceV1alpha1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*ResourceV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &ResourceV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new ResourceV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *ResourceV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new ResourceV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *ResourceV1alpha1Client { + return &ResourceV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *ResourceV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/resourceclaim.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/resourceclaim.go new file mode 100644 index 00000000000..cd2d0c78214 --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/resourceclaim.go @@ -0,0 +1,256 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + json "encoding/json" + "fmt" + "time" + + v1alpha1 "k8s.io/api/resource/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + resourcev1alpha1 "k8s.io/client-go/applyconfigurations/resource/v1alpha1" + scheme "k8s.io/client-go/kubernetes/scheme" + rest "k8s.io/client-go/rest" +) + +// ResourceClaimsGetter has a method to return a ResourceClaimInterface. +// A group's client should implement this interface. +type ResourceClaimsGetter interface { + ResourceClaims(namespace string) ResourceClaimInterface +} + +// ResourceClaimInterface has methods to work with ResourceClaim resources. +type ResourceClaimInterface interface { + Create(ctx context.Context, resourceClaim *v1alpha1.ResourceClaim, opts v1.CreateOptions) (*v1alpha1.ResourceClaim, error) + Update(ctx context.Context, resourceClaim *v1alpha1.ResourceClaim, opts v1.UpdateOptions) (*v1alpha1.ResourceClaim, error) + UpdateStatus(ctx context.Context, resourceClaim *v1alpha1.ResourceClaim, opts v1.UpdateOptions) (*v1alpha1.ResourceClaim, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ResourceClaim, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ResourceClaimList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceClaim, err error) + Apply(ctx context.Context, resourceClaim *resourcev1alpha1.ResourceClaimApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ResourceClaim, err error) + ApplyStatus(ctx context.Context, resourceClaim *resourcev1alpha1.ResourceClaimApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ResourceClaim, err error) + ResourceClaimExpansion +} + +// resourceClaims implements ResourceClaimInterface +type resourceClaims struct { + client rest.Interface + ns string +} + +// newResourceClaims returns a ResourceClaims +func newResourceClaims(c *ResourceV1alpha1Client, namespace string) *resourceClaims { + return &resourceClaims{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the resourceClaim, and returns the corresponding resourceClaim object, and an error if there is any. +func (c *resourceClaims) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ResourceClaim, err error) { + result = &v1alpha1.ResourceClaim{} + err = c.client.Get(). + Namespace(c.ns). + Resource("resourceclaims"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ResourceClaims that match those selectors. +func (c *resourceClaims) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ResourceClaimList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ResourceClaimList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("resourceclaims"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested resourceClaims. +func (c *resourceClaims) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("resourceclaims"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a resourceClaim and creates it. Returns the server's representation of the resourceClaim, and an error, if there is any. +func (c *resourceClaims) Create(ctx context.Context, resourceClaim *v1alpha1.ResourceClaim, opts v1.CreateOptions) (result *v1alpha1.ResourceClaim, err error) { + result = &v1alpha1.ResourceClaim{} + err = c.client.Post(). + Namespace(c.ns). + Resource("resourceclaims"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(resourceClaim). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a resourceClaim and updates it. Returns the server's representation of the resourceClaim, and an error, if there is any. +func (c *resourceClaims) Update(ctx context.Context, resourceClaim *v1alpha1.ResourceClaim, opts v1.UpdateOptions) (result *v1alpha1.ResourceClaim, err error) { + result = &v1alpha1.ResourceClaim{} + err = c.client.Put(). + Namespace(c.ns). + Resource("resourceclaims"). + Name(resourceClaim.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(resourceClaim). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *resourceClaims) UpdateStatus(ctx context.Context, resourceClaim *v1alpha1.ResourceClaim, opts v1.UpdateOptions) (result *v1alpha1.ResourceClaim, err error) { + result = &v1alpha1.ResourceClaim{} + err = c.client.Put(). + Namespace(c.ns). + Resource("resourceclaims"). + Name(resourceClaim.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(resourceClaim). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the resourceClaim and deletes it. Returns an error if one occurs. +func (c *resourceClaims) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("resourceclaims"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *resourceClaims) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("resourceclaims"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched resourceClaim. +func (c *resourceClaims) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceClaim, err error) { + result = &v1alpha1.ResourceClaim{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("resourceclaims"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} + +// Apply takes the given apply declarative configuration, applies it and returns the applied resourceClaim. +func (c *resourceClaims) Apply(ctx context.Context, resourceClaim *resourcev1alpha1.ResourceClaimApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ResourceClaim, err error) { + if resourceClaim == nil { + return nil, fmt.Errorf("resourceClaim provided to Apply must not be nil") + } + patchOpts := opts.ToPatchOptions() + data, err := json.Marshal(resourceClaim) + if err != nil { + return nil, err + } + name := resourceClaim.Name + if name == nil { + return nil, fmt.Errorf("resourceClaim.Name must be provided to Apply") + } + result = &v1alpha1.ResourceClaim{} + err = c.client.Patch(types.ApplyPatchType). + Namespace(c.ns). + Resource("resourceclaims"). + Name(*name). + VersionedParams(&patchOpts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} + +// ApplyStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). +func (c *resourceClaims) ApplyStatus(ctx context.Context, resourceClaim *resourcev1alpha1.ResourceClaimApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ResourceClaim, err error) { + if resourceClaim == nil { + return nil, fmt.Errorf("resourceClaim provided to Apply must not be nil") + } + patchOpts := opts.ToPatchOptions() + data, err := json.Marshal(resourceClaim) + if err != nil { + return nil, err + } + + name := resourceClaim.Name + if name == nil { + return nil, fmt.Errorf("resourceClaim.Name must be provided to Apply") + } + + result = &v1alpha1.ResourceClaim{} + err = c.client.Patch(types.ApplyPatchType). + Namespace(c.ns). + Resource("resourceclaims"). + Name(*name). + SubResource("status"). + VersionedParams(&patchOpts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/resourceclaimtemplate.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/resourceclaimtemplate.go new file mode 100644 index 00000000000..b6cc3d96eca --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/resourceclaimtemplate.go @@ -0,0 +1,208 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + json "encoding/json" + "fmt" + "time" + + v1alpha1 "k8s.io/api/resource/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + resourcev1alpha1 "k8s.io/client-go/applyconfigurations/resource/v1alpha1" + scheme "k8s.io/client-go/kubernetes/scheme" + rest "k8s.io/client-go/rest" +) + +// ResourceClaimTemplatesGetter has a method to return a ResourceClaimTemplateInterface. +// A group's client should implement this interface. +type ResourceClaimTemplatesGetter interface { + ResourceClaimTemplates(namespace string) ResourceClaimTemplateInterface +} + +// ResourceClaimTemplateInterface has methods to work with ResourceClaimTemplate resources. +type ResourceClaimTemplateInterface interface { + Create(ctx context.Context, resourceClaimTemplate *v1alpha1.ResourceClaimTemplate, opts v1.CreateOptions) (*v1alpha1.ResourceClaimTemplate, error) + Update(ctx context.Context, resourceClaimTemplate *v1alpha1.ResourceClaimTemplate, opts v1.UpdateOptions) (*v1alpha1.ResourceClaimTemplate, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ResourceClaimTemplate, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ResourceClaimTemplateList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceClaimTemplate, err error) + Apply(ctx context.Context, resourceClaimTemplate *resourcev1alpha1.ResourceClaimTemplateApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ResourceClaimTemplate, err error) + ResourceClaimTemplateExpansion +} + +// resourceClaimTemplates implements ResourceClaimTemplateInterface +type resourceClaimTemplates struct { + client rest.Interface + ns string +} + +// newResourceClaimTemplates returns a ResourceClaimTemplates +func newResourceClaimTemplates(c *ResourceV1alpha1Client, namespace string) *resourceClaimTemplates { + return &resourceClaimTemplates{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the resourceClaimTemplate, and returns the corresponding resourceClaimTemplate object, and an error if there is any. +func (c *resourceClaimTemplates) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ResourceClaimTemplate, err error) { + result = &v1alpha1.ResourceClaimTemplate{} + err = c.client.Get(). + Namespace(c.ns). + Resource("resourceclaimtemplates"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ResourceClaimTemplates that match those selectors. +func (c *resourceClaimTemplates) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ResourceClaimTemplateList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ResourceClaimTemplateList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("resourceclaimtemplates"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested resourceClaimTemplates. +func (c *resourceClaimTemplates) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("resourceclaimtemplates"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a resourceClaimTemplate and creates it. Returns the server's representation of the resourceClaimTemplate, and an error, if there is any. +func (c *resourceClaimTemplates) Create(ctx context.Context, resourceClaimTemplate *v1alpha1.ResourceClaimTemplate, opts v1.CreateOptions) (result *v1alpha1.ResourceClaimTemplate, err error) { + result = &v1alpha1.ResourceClaimTemplate{} + err = c.client.Post(). + Namespace(c.ns). + Resource("resourceclaimtemplates"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(resourceClaimTemplate). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a resourceClaimTemplate and updates it. Returns the server's representation of the resourceClaimTemplate, and an error, if there is any. +func (c *resourceClaimTemplates) Update(ctx context.Context, resourceClaimTemplate *v1alpha1.ResourceClaimTemplate, opts v1.UpdateOptions) (result *v1alpha1.ResourceClaimTemplate, err error) { + result = &v1alpha1.ResourceClaimTemplate{} + err = c.client.Put(). + Namespace(c.ns). + Resource("resourceclaimtemplates"). + Name(resourceClaimTemplate.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(resourceClaimTemplate). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the resourceClaimTemplate and deletes it. Returns an error if one occurs. +func (c *resourceClaimTemplates) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("resourceclaimtemplates"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *resourceClaimTemplates) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("resourceclaimtemplates"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched resourceClaimTemplate. +func (c *resourceClaimTemplates) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceClaimTemplate, err error) { + result = &v1alpha1.ResourceClaimTemplate{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("resourceclaimtemplates"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} + +// Apply takes the given apply declarative configuration, applies it and returns the applied resourceClaimTemplate. +func (c *resourceClaimTemplates) Apply(ctx context.Context, resourceClaimTemplate *resourcev1alpha1.ResourceClaimTemplateApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ResourceClaimTemplate, err error) { + if resourceClaimTemplate == nil { + return nil, fmt.Errorf("resourceClaimTemplate provided to Apply must not be nil") + } + patchOpts := opts.ToPatchOptions() + data, err := json.Marshal(resourceClaimTemplate) + if err != nil { + return nil, err + } + name := resourceClaimTemplate.Name + if name == nil { + return nil, fmt.Errorf("resourceClaimTemplate.Name must be provided to Apply") + } + result = &v1alpha1.ResourceClaimTemplate{} + err = c.client.Patch(types.ApplyPatchType). + Namespace(c.ns). + Resource("resourceclaimtemplates"). + Name(*name). + VersionedParams(&patchOpts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/resourceclass.go b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/resourceclass.go new file mode 100644 index 00000000000..9c8b454639a --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/resource/v1alpha1/resourceclass.go @@ -0,0 +1,197 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + json "encoding/json" + "fmt" + "time" + + v1alpha1 "k8s.io/api/resource/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + resourcev1alpha1 "k8s.io/client-go/applyconfigurations/resource/v1alpha1" + scheme "k8s.io/client-go/kubernetes/scheme" + rest "k8s.io/client-go/rest" +) + +// ResourceClassesGetter has a method to return a ResourceClassInterface. +// A group's client should implement this interface. +type ResourceClassesGetter interface { + ResourceClasses() ResourceClassInterface +} + +// ResourceClassInterface has methods to work with ResourceClass resources. +type ResourceClassInterface interface { + Create(ctx context.Context, resourceClass *v1alpha1.ResourceClass, opts v1.CreateOptions) (*v1alpha1.ResourceClass, error) + Update(ctx context.Context, resourceClass *v1alpha1.ResourceClass, opts v1.UpdateOptions) (*v1alpha1.ResourceClass, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ResourceClass, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ResourceClassList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceClass, err error) + Apply(ctx context.Context, resourceClass *resourcev1alpha1.ResourceClassApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ResourceClass, err error) + ResourceClassExpansion +} + +// resourceClasses implements ResourceClassInterface +type resourceClasses struct { + client rest.Interface +} + +// newResourceClasses returns a ResourceClasses +func newResourceClasses(c *ResourceV1alpha1Client) *resourceClasses { + return &resourceClasses{ + client: c.RESTClient(), + } +} + +// Get takes name of the resourceClass, and returns the corresponding resourceClass object, and an error if there is any. +func (c *resourceClasses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ResourceClass, err error) { + result = &v1alpha1.ResourceClass{} + err = c.client.Get(). + Resource("resourceclasses"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ResourceClasses that match those selectors. +func (c *resourceClasses) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ResourceClassList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ResourceClassList{} + err = c.client.Get(). + Resource("resourceclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested resourceClasses. +func (c *resourceClasses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("resourceclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a resourceClass and creates it. Returns the server's representation of the resourceClass, and an error, if there is any. +func (c *resourceClasses) Create(ctx context.Context, resourceClass *v1alpha1.ResourceClass, opts v1.CreateOptions) (result *v1alpha1.ResourceClass, err error) { + result = &v1alpha1.ResourceClass{} + err = c.client.Post(). + Resource("resourceclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(resourceClass). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a resourceClass and updates it. Returns the server's representation of the resourceClass, and an error, if there is any. +func (c *resourceClasses) Update(ctx context.Context, resourceClass *v1alpha1.ResourceClass, opts v1.UpdateOptions) (result *v1alpha1.ResourceClass, err error) { + result = &v1alpha1.ResourceClass{} + err = c.client.Put(). + Resource("resourceclasses"). + Name(resourceClass.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(resourceClass). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the resourceClass and deletes it. Returns an error if one occurs. +func (c *resourceClasses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Resource("resourceclasses"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *resourceClasses) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("resourceclasses"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched resourceClass. +func (c *resourceClasses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceClass, err error) { + result = &v1alpha1.ResourceClass{} + err = c.client.Patch(pt). + Resource("resourceclasses"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} + +// Apply takes the given apply declarative configuration, applies it and returns the applied resourceClass. +func (c *resourceClasses) Apply(ctx context.Context, resourceClass *resourcev1alpha1.ResourceClassApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ResourceClass, err error) { + if resourceClass == nil { + return nil, fmt.Errorf("resourceClass provided to Apply must not be nil") + } + patchOpts := opts.ToPatchOptions() + data, err := json.Marshal(resourceClass) + if err != nil { + return nil, err + } + name := resourceClass.Name + if name == nil { + return nil, fmt.Errorf("resourceClass.Name must be provided to Apply") + } + result = &v1alpha1.ResourceClass{} + err = c.client.Patch(types.ApplyPatchType). + Resource("resourceclasses"). + Name(*name). + VersionedParams(&patchOpts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/staging/src/k8s.io/client-go/listers/resource/v1alpha1/expansion_generated.go b/staging/src/k8s.io/client-go/listers/resource/v1alpha1/expansion_generated.go new file mode 100644 index 00000000000..94885e784fb --- /dev/null +++ b/staging/src/k8s.io/client-go/listers/resource/v1alpha1/expansion_generated.go @@ -0,0 +1,47 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// PodSchedulingListerExpansion allows custom methods to be added to +// PodSchedulingLister. +type PodSchedulingListerExpansion interface{} + +// PodSchedulingNamespaceListerExpansion allows custom methods to be added to +// PodSchedulingNamespaceLister. +type PodSchedulingNamespaceListerExpansion interface{} + +// ResourceClaimListerExpansion allows custom methods to be added to +// ResourceClaimLister. +type ResourceClaimListerExpansion interface{} + +// ResourceClaimNamespaceListerExpansion allows custom methods to be added to +// ResourceClaimNamespaceLister. +type ResourceClaimNamespaceListerExpansion interface{} + +// ResourceClaimTemplateListerExpansion allows custom methods to be added to +// ResourceClaimTemplateLister. +type ResourceClaimTemplateListerExpansion interface{} + +// ResourceClaimTemplateNamespaceListerExpansion allows custom methods to be added to +// ResourceClaimTemplateNamespaceLister. +type ResourceClaimTemplateNamespaceListerExpansion interface{} + +// ResourceClassListerExpansion allows custom methods to be added to +// ResourceClassLister. +type ResourceClassListerExpansion interface{} diff --git a/staging/src/k8s.io/client-go/listers/resource/v1alpha1/podscheduling.go b/staging/src/k8s.io/client-go/listers/resource/v1alpha1/podscheduling.go new file mode 100644 index 00000000000..fe43713710a --- /dev/null +++ b/staging/src/k8s.io/client-go/listers/resource/v1alpha1/podscheduling.go @@ -0,0 +1,99 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "k8s.io/api/resource/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// PodSchedulingLister helps list PodSchedulings. +// All objects returned here must be treated as read-only. +type PodSchedulingLister interface { + // List lists all PodSchedulings in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.PodScheduling, err error) + // PodSchedulings returns an object that can list and get PodSchedulings. + PodSchedulings(namespace string) PodSchedulingNamespaceLister + PodSchedulingListerExpansion +} + +// podSchedulingLister implements the PodSchedulingLister interface. +type podSchedulingLister struct { + indexer cache.Indexer +} + +// NewPodSchedulingLister returns a new PodSchedulingLister. +func NewPodSchedulingLister(indexer cache.Indexer) PodSchedulingLister { + return &podSchedulingLister{indexer: indexer} +} + +// List lists all PodSchedulings in the indexer. +func (s *podSchedulingLister) List(selector labels.Selector) (ret []*v1alpha1.PodScheduling, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.PodScheduling)) + }) + return ret, err +} + +// PodSchedulings returns an object that can list and get PodSchedulings. +func (s *podSchedulingLister) PodSchedulings(namespace string) PodSchedulingNamespaceLister { + return podSchedulingNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// PodSchedulingNamespaceLister helps list and get PodSchedulings. +// All objects returned here must be treated as read-only. +type PodSchedulingNamespaceLister interface { + // List lists all PodSchedulings in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.PodScheduling, err error) + // Get retrieves the PodScheduling from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.PodScheduling, error) + PodSchedulingNamespaceListerExpansion +} + +// podSchedulingNamespaceLister implements the PodSchedulingNamespaceLister +// interface. +type podSchedulingNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all PodSchedulings in the indexer for a given namespace. +func (s podSchedulingNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.PodScheduling, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.PodScheduling)) + }) + return ret, err +} + +// Get retrieves the PodScheduling from the indexer for a given namespace and name. +func (s podSchedulingNamespaceLister) Get(name string) (*v1alpha1.PodScheduling, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("podscheduling"), name) + } + return obj.(*v1alpha1.PodScheduling), nil +} diff --git a/staging/src/k8s.io/client-go/listers/resource/v1alpha1/resourceclaim.go b/staging/src/k8s.io/client-go/listers/resource/v1alpha1/resourceclaim.go new file mode 100644 index 00000000000..05d5e0cfa4d --- /dev/null +++ b/staging/src/k8s.io/client-go/listers/resource/v1alpha1/resourceclaim.go @@ -0,0 +1,99 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "k8s.io/api/resource/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ResourceClaimLister helps list ResourceClaims. +// All objects returned here must be treated as read-only. +type ResourceClaimLister interface { + // List lists all ResourceClaims in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ResourceClaim, err error) + // ResourceClaims returns an object that can list and get ResourceClaims. + ResourceClaims(namespace string) ResourceClaimNamespaceLister + ResourceClaimListerExpansion +} + +// resourceClaimLister implements the ResourceClaimLister interface. +type resourceClaimLister struct { + indexer cache.Indexer +} + +// NewResourceClaimLister returns a new ResourceClaimLister. +func NewResourceClaimLister(indexer cache.Indexer) ResourceClaimLister { + return &resourceClaimLister{indexer: indexer} +} + +// List lists all ResourceClaims in the indexer. +func (s *resourceClaimLister) List(selector labels.Selector) (ret []*v1alpha1.ResourceClaim, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ResourceClaim)) + }) + return ret, err +} + +// ResourceClaims returns an object that can list and get ResourceClaims. +func (s *resourceClaimLister) ResourceClaims(namespace string) ResourceClaimNamespaceLister { + return resourceClaimNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ResourceClaimNamespaceLister helps list and get ResourceClaims. +// All objects returned here must be treated as read-only. +type ResourceClaimNamespaceLister interface { + // List lists all ResourceClaims in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ResourceClaim, err error) + // Get retrieves the ResourceClaim from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.ResourceClaim, error) + ResourceClaimNamespaceListerExpansion +} + +// resourceClaimNamespaceLister implements the ResourceClaimNamespaceLister +// interface. +type resourceClaimNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ResourceClaims in the indexer for a given namespace. +func (s resourceClaimNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ResourceClaim, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ResourceClaim)) + }) + return ret, err +} + +// Get retrieves the ResourceClaim from the indexer for a given namespace and name. +func (s resourceClaimNamespaceLister) Get(name string) (*v1alpha1.ResourceClaim, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("resourceclaim"), name) + } + return obj.(*v1alpha1.ResourceClaim), nil +} diff --git a/staging/src/k8s.io/client-go/listers/resource/v1alpha1/resourceclaimtemplate.go b/staging/src/k8s.io/client-go/listers/resource/v1alpha1/resourceclaimtemplate.go new file mode 100644 index 00000000000..97acddc7af5 --- /dev/null +++ b/staging/src/k8s.io/client-go/listers/resource/v1alpha1/resourceclaimtemplate.go @@ -0,0 +1,99 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "k8s.io/api/resource/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ResourceClaimTemplateLister helps list ResourceClaimTemplates. +// All objects returned here must be treated as read-only. +type ResourceClaimTemplateLister interface { + // List lists all ResourceClaimTemplates in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ResourceClaimTemplate, err error) + // ResourceClaimTemplates returns an object that can list and get ResourceClaimTemplates. + ResourceClaimTemplates(namespace string) ResourceClaimTemplateNamespaceLister + ResourceClaimTemplateListerExpansion +} + +// resourceClaimTemplateLister implements the ResourceClaimTemplateLister interface. +type resourceClaimTemplateLister struct { + indexer cache.Indexer +} + +// NewResourceClaimTemplateLister returns a new ResourceClaimTemplateLister. +func NewResourceClaimTemplateLister(indexer cache.Indexer) ResourceClaimTemplateLister { + return &resourceClaimTemplateLister{indexer: indexer} +} + +// List lists all ResourceClaimTemplates in the indexer. +func (s *resourceClaimTemplateLister) List(selector labels.Selector) (ret []*v1alpha1.ResourceClaimTemplate, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ResourceClaimTemplate)) + }) + return ret, err +} + +// ResourceClaimTemplates returns an object that can list and get ResourceClaimTemplates. +func (s *resourceClaimTemplateLister) ResourceClaimTemplates(namespace string) ResourceClaimTemplateNamespaceLister { + return resourceClaimTemplateNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ResourceClaimTemplateNamespaceLister helps list and get ResourceClaimTemplates. +// All objects returned here must be treated as read-only. +type ResourceClaimTemplateNamespaceLister interface { + // List lists all ResourceClaimTemplates in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ResourceClaimTemplate, err error) + // Get retrieves the ResourceClaimTemplate from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.ResourceClaimTemplate, error) + ResourceClaimTemplateNamespaceListerExpansion +} + +// resourceClaimTemplateNamespaceLister implements the ResourceClaimTemplateNamespaceLister +// interface. +type resourceClaimTemplateNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ResourceClaimTemplates in the indexer for a given namespace. +func (s resourceClaimTemplateNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ResourceClaimTemplate, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ResourceClaimTemplate)) + }) + return ret, err +} + +// Get retrieves the ResourceClaimTemplate from the indexer for a given namespace and name. +func (s resourceClaimTemplateNamespaceLister) Get(name string) (*v1alpha1.ResourceClaimTemplate, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("resourceclaimtemplate"), name) + } + return obj.(*v1alpha1.ResourceClaimTemplate), nil +} diff --git a/staging/src/k8s.io/client-go/listers/resource/v1alpha1/resourceclass.go b/staging/src/k8s.io/client-go/listers/resource/v1alpha1/resourceclass.go new file mode 100644 index 00000000000..8d4dbf4d04c --- /dev/null +++ b/staging/src/k8s.io/client-go/listers/resource/v1alpha1/resourceclass.go @@ -0,0 +1,68 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "k8s.io/api/resource/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ResourceClassLister helps list ResourceClasses. +// All objects returned here must be treated as read-only. +type ResourceClassLister interface { + // List lists all ResourceClasses in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ResourceClass, err error) + // Get retrieves the ResourceClass from the index for a given name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.ResourceClass, error) + ResourceClassListerExpansion +} + +// resourceClassLister implements the ResourceClassLister interface. +type resourceClassLister struct { + indexer cache.Indexer +} + +// NewResourceClassLister returns a new ResourceClassLister. +func NewResourceClassLister(indexer cache.Indexer) ResourceClassLister { + return &resourceClassLister{indexer: indexer} +} + +// List lists all ResourceClasses in the indexer. +func (s *resourceClassLister) List(selector labels.Selector) (ret []*v1alpha1.ResourceClass, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ResourceClass)) + }) + return ret, err +} + +// Get retrieves the ResourceClass from the index for a given name. +func (s *resourceClassLister) Get(name string) (*v1alpha1.ResourceClass, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("resourceclass"), name) + } + return obj.(*v1alpha1.ResourceClass), nil +} diff --git a/staging/src/k8s.io/dynamic-resource-allocation/.github/PULL_REQUEST_TEMPLATE.md b/staging/src/k8s.io/dynamic-resource-allocation/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000000..e7e5eb834b2 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,2 @@ +Sorry, we do not accept changes directly against this repository. Please see +CONTRIBUTING.md for information on where and how to contribute instead. diff --git a/staging/src/k8s.io/dynamic-resource-allocation/CONTRIBUTING.md b/staging/src/k8s.io/dynamic-resource-allocation/CONTRIBUTING.md new file mode 100644 index 00000000000..95dce2de149 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/CONTRIBUTING.md @@ -0,0 +1,7 @@ +# Contributing guidelines + +Do not open pull requests directly against this repository, they will be ignored. Instead, please open pull requests against [kubernetes/kubernetes](https://git.k8s.io/kubernetes/). Please follow the same [contributing guide](https://git.k8s.io/kubernetes/CONTRIBUTING.md) you would follow for any other pull request made to kubernetes/kubernetes. + +This repository is published from [kubernetes/kubernetes/staging/src/k8s.io/dynamic-resource-allocation](https://git.k8s.io/kubernetes/staging/src/k8s.io/dynamic-resource-allocation) by the [kubernetes publishing-bot](https://git.k8s.io/publishing-bot). + +Please see [Staging Directory and Publishing](https://git.k8s.io/community/contributors/devel/sig-architecture/staging.md) for more information diff --git a/staging/src/k8s.io/dynamic-resource-allocation/LICENSE b/staging/src/k8s.io/dynamic-resource-allocation/LICENSE new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/staging/src/k8s.io/dynamic-resource-allocation/OWNERS b/staging/src/k8s.io/dynamic-resource-allocation/OWNERS new file mode 100644 index 00000000000..03cc9aff5b4 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/OWNERS @@ -0,0 +1,11 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - klueska + - pohly +reviewers: + - klueska + - pohly + - bart0sh +labels: + - sig/node diff --git a/staging/src/k8s.io/dynamic-resource-allocation/README.md b/staging/src/k8s.io/dynamic-resource-allocation/README.md new file mode 100644 index 00000000000..194ae12bf38 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/README.md @@ -0,0 +1,26 @@ +# dynamic-resource-allocation + +## Purpose + +This repository contains packages related to the [dynamic resource +allocation](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3063-dynamic-resource-allocation) +feature. + +## Compatibility + +There are *NO compatibility guarantees* for this repository, yet. It is in direct support of Kubernetes, so branches +will track Kubernetes and be compatible with that repo. + +## Where does it come from? + +This repository is synced from https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/dynamic-resource-allocation. +Code changes are made in that location, merged into `k8s.io/kubernetes` and later synced here. + +## Things you should *NOT* do + + 1. Directly modify any files in this repo. Those are driven from `k8s.io/kubernetes/staging/src/k8s.io/dynamic-resource-allocation`. + 2. Expect compatibility. This repo is changing quickly in direct support of Kubernetes. + +### OWNERS + +SIG Node owns the code. diff --git a/staging/src/k8s.io/dynamic-resource-allocation/SECURITY_CONTACTS b/staging/src/k8s.io/dynamic-resource-allocation/SECURITY_CONTACTS new file mode 100644 index 00000000000..253cfa100c4 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/SECURITY_CONTACTS @@ -0,0 +1,14 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Committee to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +klueska +pohly diff --git a/staging/src/k8s.io/dynamic-resource-allocation/code-of-conduct.md b/staging/src/k8s.io/dynamic-resource-allocation/code-of-conduct.md new file mode 100644 index 00000000000..0d15c00cf32 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/code-of-conduct.md @@ -0,0 +1,3 @@ +# Kubernetes Community Code of Conduct + +Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) diff --git a/staging/src/k8s.io/dynamic-resource-allocation/controller/controller.go b/staging/src/k8s.io/dynamic-resource-allocation/controller/controller.go new file mode 100644 index 00000000000..c59724123a6 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/controller/controller.go @@ -0,0 +1,809 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controller + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/go-logr/logr" + "github.com/google/go-cmp/cmp" + + v1 "k8s.io/api/core/v1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + corev1types "k8s.io/client-go/kubernetes/typed/core/v1" + resourcev1alpha1listers "k8s.io/client-go/listers/resource/v1alpha1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/workqueue" + "k8s.io/dynamic-resource-allocation/resourceclaim" + "k8s.io/klog/v2" +) + +// Controller watches ResourceClaims and triggers allocation and deallocation +// as needed. +type Controller interface { + // Run starts the controller. + Run(workers int) +} + +// Driver provides the actual allocation and deallocation operations. +type Driver interface { + // GetClassParameters gets called to retrieve the parameter object + // referenced by a class. The content should be validated now if + // possible. class.Parameters may be nil. + // + // The caller will wrap the error to include the parameter reference. + GetClassParameters(ctx context.Context, class *resourcev1alpha1.ResourceClass) (interface{}, error) + + // GetClaimParameters gets called to retrieve the parameter object + // referenced by a claim. The content should be validated now if + // possible. claim.Spec.Parameters may be nil. + // + // The caller will wrap the error to include the parameter reference. + GetClaimParameters(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, class *resourcev1alpha1.ResourceClass, classParameters interface{}) (interface{}, error) + + // Allocate gets called when a ResourceClaim is ready to be allocated. + // The selectedNode is empty for ResourceClaims with immediate + // allocation, in which case the resource driver decides itself where + // to allocate. If there is already an on-going allocation, the driver + // may finish it and ignore the new parameters or abort the on-going + // allocation and try again with the new parameters. + // + // Parameters have been retrieved earlier. + // + // If selectedNode is set, the driver must attempt to allocate for that + // node. If that is not possible, it must return an error. The + // controller will call UnsuitableNodes and pass the new information to + // the scheduler, which then will lead to selecting a diffent node + // if the current one is not suitable. + // + // The objects are read-only and must not be modified. This call + // must be idempotent. + Allocate(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, claimParameters interface{}, class *resourcev1alpha1.ResourceClass, classParameters interface{}, selectedNode string) (*resourcev1alpha1.AllocationResult, error) + + // Deallocate gets called when a ResourceClaim is ready to be + // freed. + // + // The claim is read-only and must not be modified. This call must be + // idempotent. In particular it must not return an error when the claim + // is currently not allocated. + // + // Deallocate may get called when a previous allocation got + // interrupted. Deallocate must then stop any on-going allocation + // activity and free resources before returning without an error. + Deallocate(ctx context.Context, claim *resourcev1alpha1.ResourceClaim) error + + // UnsuitableNodes checks all pending claims with delayed allocation + // for a pod. All claims are ready for allocation by the driver + // and parameters have been retrieved. + // + // The driver may consider each claim in isolation, but it's better + // to mark nodes as unsuitable for all claims if it not all claims + // can be allocated for it (for example, two GPUs requested but + // the node only has one). + // + // The result of the check is in ClaimAllocation.UnsuitableNodes. + // An error indicates that the entire check must be repeated. + UnsuitableNodes(ctx context.Context, pod *v1.Pod, claims []*ClaimAllocation, potentialNodes []string) error +} + +// ClaimAllocation represents information about one particular +// pod.Spec.ResourceClaim entry. +type ClaimAllocation struct { + PodClaimName string + Claim *resourcev1alpha1.ResourceClaim + Class *resourcev1alpha1.ResourceClass + ClaimParameters interface{} + ClassParameters interface{} + + // UnsuitableNodes needs to be filled in by the driver when + // Driver.UnsuitableNodes gets called. + UnsuitableNodes []string +} + +type controller struct { + ctx context.Context + logger klog.Logger + name string + finalizer string + driver Driver + kubeClient kubernetes.Interface + queue workqueue.RateLimitingInterface + eventRecorder record.EventRecorder + rcLister resourcev1alpha1listers.ResourceClassLister + rcSynced cache.InformerSynced + claimCache cache.MutationCache + podSchedulingLister resourcev1alpha1listers.PodSchedulingLister + claimSynced cache.InformerSynced + podSchedulingSynced cache.InformerSynced +} + +// TODO: make it configurable +var recheckDelay = 30 * time.Second + +// New creates a new controller. +func New( + ctx context.Context, + name string, + driver Driver, + kubeClient kubernetes.Interface, + informerFactory informers.SharedInformerFactory) Controller { + logger := klog.LoggerWithName(klog.FromContext(ctx), "resource controller") + rcInformer := informerFactory.Resource().V1alpha1().ResourceClasses() + claimInformer := informerFactory.Resource().V1alpha1().ResourceClaims() + podSchedulingInformer := informerFactory.Resource().V1alpha1().PodSchedulings() + + eventBroadcaster := record.NewBroadcaster() + // TODO: use contextual logging in eventBroadcaster once it + // supports it. There is a StartStructuredLogging API, but it + // uses the global klog, which is worse than redirecting an unstructured + // string into our logger, in particular during testing. + eventBroadcaster.StartLogging(func(format string, args ...interface{}) { + helper, logger := logger.WithCallStackHelper() + helper() + logger.V(2).Info(fmt.Sprintf(format, args...)) + }) + eventBroadcaster.StartRecordingToSink(&corev1types.EventSinkImpl{Interface: kubeClient.CoreV1().Events(v1.NamespaceAll)}) + eventRecorder := eventBroadcaster.NewRecorder(scheme.Scheme, + v1.EventSource{Component: fmt.Sprintf("resource driver %s", name)}) + + // The work queue contains either keys for claims or PodScheduling objects. + queue := workqueue.NewNamedRateLimitingQueue( + workqueue.DefaultControllerRateLimiter(), fmt.Sprintf("%s-queue", name)) + + // The mutation cache acts as an additional layer for the informer + // cache and after an update made by the controller returns a more + // recent copy until the informer catches up. + claimInformerCache := claimInformer.Informer().GetIndexer() + claimCache := cache.NewIntegerResourceVersionMutationCache(claimInformerCache, claimInformerCache, 60*time.Second, + false /* only cache updated claims that exist in the informer cache */) + + ctrl := &controller{ + ctx: ctx, + logger: logger, + name: name, + finalizer: name + "/deletion-protection", + driver: driver, + kubeClient: kubeClient, + rcLister: rcInformer.Lister(), + rcSynced: rcInformer.Informer().HasSynced, + claimCache: claimCache, + claimSynced: claimInformer.Informer().HasSynced, + podSchedulingLister: podSchedulingInformer.Lister(), + podSchedulingSynced: podSchedulingInformer.Informer().HasSynced, + queue: queue, + eventRecorder: eventRecorder, + } + + loggerV6 := logger.V(6) + if loggerV6.Enabled() { + resourceClaimLogger := klog.LoggerWithValues(loggerV6, "type", "ResourceClaim") + _, _ = claimInformer.Informer().AddEventHandler(resourceEventHandlerFuncs(&resourceClaimLogger, ctrl)) + podSchedulingLogger := klog.LoggerWithValues(loggerV6, "type", "PodScheduling") + _, _ = podSchedulingInformer.Informer().AddEventHandler(resourceEventHandlerFuncs(&podSchedulingLogger, ctrl)) + } else { + _, _ = claimInformer.Informer().AddEventHandler(resourceEventHandlerFuncs(nil, ctrl)) + _, _ = podSchedulingInformer.Informer().AddEventHandler(resourceEventHandlerFuncs(nil, ctrl)) + } + + return ctrl +} + +func resourceEventHandlerFuncs(logger *klog.Logger, ctrl *controller) cache.ResourceEventHandlerFuncs { + return cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + ctrl.add(logger, obj) + }, + UpdateFunc: func(oldObj, newObj interface{}) { + ctrl.update(logger, oldObj, newObj) + }, + DeleteFunc: ctrl.delete, + } +} + +const ( + claimKeyPrefix = "claim:" + podSchedulingKeyPrefix = "podscheduling:" +) + +func (ctrl *controller) add(logger *klog.Logger, obj interface{}) { + if logger != nil { + logger.Info("new object", "content", prettyPrint(obj)) + } + ctrl.addNewOrUpdated("Adding new work item", obj) +} + +func (ctrl *controller) update(logger *klog.Logger, oldObj, newObj interface{}) { + if logger != nil { + diff := cmp.Diff(oldObj, newObj) + logger.Info("updated object", "content", prettyPrint(newObj), "diff", diff) + } + ctrl.addNewOrUpdated("Adding updated work item", newObj) +} + +func (ctrl *controller) addNewOrUpdated(msg string, obj interface{}) { + objKey, err := getKey(obj) + if err != nil { + ctrl.logger.Error(err, "Failed to get key", "obj", obj) + return + } + ctrl.logger.V(5).Info(msg, "key", objKey) + ctrl.queue.Add(objKey) +} + +func (ctrl *controller) delete(obj interface{}) { + objKey, err := getKey(obj) + if err != nil { + return + } + ctrl.logger.V(5).Info("Removing deleted work item", "key", objKey) + ctrl.queue.Forget(objKey) +} + +func getKey(obj interface{}) (string, error) { + objKey, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) + if err != nil { + return "", err + } + prefix := "" + switch obj.(type) { + case *resourcev1alpha1.ResourceClaim: + prefix = claimKeyPrefix + case *resourcev1alpha1.PodScheduling: + prefix = podSchedulingKeyPrefix + default: + return "", fmt.Errorf("unexpected object: %T", obj) + } + + return prefix + objKey, nil +} + +// Run starts the controller. +func (ctrl *controller) Run(workers int) { + defer ctrl.queue.ShutDown() + + ctrl.logger.Info("Starting", "driver", ctrl.name) + defer ctrl.logger.Info("Shutting down", "driver", ctrl.name) + + stopCh := ctrl.ctx.Done() + + if !cache.WaitForCacheSync(stopCh, ctrl.rcSynced, ctrl.claimSynced, ctrl.podSchedulingSynced) { + ctrl.logger.Error(nil, "Cannot sync caches") + return + } + + for i := 0; i < workers; i++ { + go wait.Until(ctrl.sync, 0, stopCh) + } + + <-stopCh +} + +// errRequeue is a special error instance that functions can return +// to request silent requeueing (not logged as error, no event). +// Uses exponential backoff. +var errRequeue = errors.New("requeue") + +// errPeriodic is a special error instance that functions can return +// to request silent instance that functions can return +// to request silent retrying at a fixed rate. +var errPeriodic = errors.New("periodic") + +// sync is the main worker. +func (ctrl *controller) sync() { + key, quit := ctrl.queue.Get() + if quit { + return + } + defer ctrl.queue.Done(key) + + logger := klog.LoggerWithValues(ctrl.logger, "key", key) + ctx := klog.NewContext(ctrl.ctx, logger) + logger.V(4).Info("processing") + obj, err := ctrl.syncKey(ctx, key.(string)) + switch err { + case nil: + logger.V(5).Info("completed") + ctrl.queue.Forget(key) + case errRequeue: + logger.V(5).Info("requeue") + ctrl.queue.AddRateLimited(key) + case errPeriodic: + logger.V(5).Info("recheck periodically") + ctrl.queue.AddAfter(key, recheckDelay) + default: + logger.Error(err, "processing failed") + if obj != nil { + // TODO: We don't know here *what* failed. Determine based on error? + ctrl.eventRecorder.Event(obj, v1.EventTypeWarning, "Failed", err.Error()) + } + ctrl.queue.AddRateLimited(key) + } +} + +// syncKey looks up a ResourceClaim by its key and processes it. +func (ctrl *controller) syncKey(ctx context.Context, key string) (obj runtime.Object, finalErr error) { + sep := strings.Index(key, ":") + if sep < 0 { + return nil, fmt.Errorf("unexpected key: %s", key) + } + prefix, object := key[0:sep+1], key[sep+1:] + namespace, name, err := cache.SplitMetaNamespaceKey(object) + if err != nil { + return nil, err + } + + switch prefix { + case claimKeyPrefix: + claim, err := ctrl.getCachedClaim(ctx, object) + if claim == nil || err != nil { + return nil, err + } + obj, finalErr = claim, ctrl.syncClaim(ctx, claim) + case podSchedulingKeyPrefix: + podScheduling, err := ctrl.podSchedulingLister.PodSchedulings(namespace).Get(name) + if err != nil { + if k8serrors.IsNotFound(err) { + klog.FromContext(ctx).V(5).Info("PodScheduling was deleted, no need to process it") + return nil, nil + } + return nil, err + } + obj, finalErr = podScheduling, ctrl.syncPodScheduling(ctx, podScheduling) + } + return +} + +func (ctrl *controller) getCachedClaim(ctx context.Context, key string) (*resourcev1alpha1.ResourceClaim, error) { + claimObj, exists, err := ctrl.claimCache.GetByKey(key) + if !exists || k8serrors.IsNotFound(err) { + klog.FromContext(ctx).V(5).Info("ResourceClaim not found, no need to process it") + return nil, nil + } + if err != nil { + return nil, err + } + claim, ok := claimObj.(*resourcev1alpha1.ResourceClaim) + if !ok { + return nil, fmt.Errorf("internal error: got %T instead of *resourcev1alpha1.ResourceClaim from claim cache", claimObj) + } + return claim, nil +} + +// syncClaim determines which next action may be needed for a ResourceClaim +// and does it. +func (ctrl *controller) syncClaim(ctx context.Context, claim *resourcev1alpha1.ResourceClaim) error { + var err error + logger := klog.FromContext(ctx) + + if len(claim.Status.ReservedFor) > 0 { + // In use. Nothing that we can do for it now. + if loggerV6 := logger.V(6); loggerV6.Enabled() { + loggerV6.Info("ResourceClaim in use", "reservedFor", claim.Status.ReservedFor) + } else { + logger.V(5).Info("ResourceClaim in use") + } + return nil + } + + if claim.DeletionTimestamp != nil || + claim.Status.DeallocationRequested { + // Ready for deallocation. We might have our finalizer set. The + // finalizer is specific to the driver, therefore we know that + // this claim is "ours" when the finalizer is set. + hasFinalizer := ctrl.hasFinalizer(claim) + logger.V(5).Info("ResourceClaim ready for deallocation", "deallocationRequested", claim.Status.DeallocationRequested, "deletionTimestamp", claim.DeletionTimestamp, "allocated", claim.Status.Allocation != nil, "hasFinalizer", hasFinalizer) + if hasFinalizer { + claim = claim.DeepCopy() + if claim.Status.Allocation != nil { + // Allocation was completed. Deallocate before proceeding. + if err := ctrl.driver.Deallocate(ctx, claim); err != nil { + return fmt.Errorf("deallocate: %v", err) + } + claim.Status.Allocation = nil + claim.Status.DriverName = "" + claim.Status.DeallocationRequested = false + claim, err = ctrl.kubeClient.ResourceV1alpha1().ResourceClaims(claim.Namespace).UpdateStatus(ctx, claim, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("remove allocation: %v", err) + } + ctrl.claimCache.Mutation(claim) + } else { + // Ensure that there is no on-going allocation. + if err := ctrl.driver.Deallocate(ctx, claim); err != nil { + return fmt.Errorf("stop allocation: %v", err) + } + } + + if claim.Status.DeallocationRequested { + // Still need to remove it. + claim.Status.DeallocationRequested = false + claim, err = ctrl.kubeClient.ResourceV1alpha1().ResourceClaims(claim.Namespace).UpdateStatus(ctx, claim, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("remove deallocation: %v", err) + } + ctrl.claimCache.Mutation(claim) + } + + claim.Finalizers = ctrl.removeFinalizer(claim.Finalizers) + claim, err = ctrl.kubeClient.ResourceV1alpha1().ResourceClaims(claim.Namespace).Update(ctx, claim, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("remove finalizer: %v", err) + } + ctrl.claimCache.Mutation(claim) + } + + // Nothing further to do. The apiserver should remove it shortly. + return nil + + } + + if claim.Status.Allocation != nil { + logger.V(5).Info("ResourceClaim is allocated") + return nil + } + if claim.Spec.AllocationMode != resourcev1alpha1.AllocationModeImmediate { + logger.V(5).Info("ResourceClaim waiting for first consumer") + return nil + } + + // We need the ResourceClass to determine whether we should allocate it. + class, err := ctrl.rcLister.Get(claim.Spec.ResourceClassName) + if err != nil { + return err + } + if class.DriverName != ctrl.name { + // Not ours *at the moment*. This can change, so requeue and + // check again. We could trigger a faster check when the + // ResourceClass changes, but that shouldn't occur much in + // practice and thus isn't worth the effort. + // + // We use exponential backoff because it is unlikely that + // the ResourceClass changes much. + logger.V(5).Info("ResourceClaim is handled by other driver", "driver", class.DriverName) + return errRequeue + } + + // Check parameters. + claimParameters, classParameters, err := ctrl.getParameters(ctx, claim, class) + if err != nil { + return err + } + + return ctrl.allocateClaim(ctx, claim, claimParameters, class, classParameters, "", nil) +} + +func (ctrl *controller) getParameters(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, class *resourcev1alpha1.ResourceClass) (claimParameters, classParameters interface{}, err error) { + classParameters, err = ctrl.driver.GetClassParameters(ctx, class) + if err != nil { + err = fmt.Errorf("class parameters %s: %v", class.ParametersRef, err) + return + } + claimParameters, err = ctrl.driver.GetClaimParameters(ctx, claim, class, classParameters) + if err != nil { + err = fmt.Errorf("claim parameters %s: %v", claim.Spec.ParametersRef, err) + return + } + return +} + +func (ctrl *controller) allocateClaim(ctx context.Context, + claim *resourcev1alpha1.ResourceClaim, claimParameters interface{}, + class *resourcev1alpha1.ResourceClass, classParameters interface{}, + selectedNode string, + selectedUser *resourcev1alpha1.ResourceClaimConsumerReference) error { + logger := klog.FromContext(ctx) + + if claim.Status.Allocation != nil { + // This can happen when two PodScheduling objects trigger + // allocation attempts (first one wins) or when we see the + // update of the PodScheduling object. + logger.V(5).Info("Claim already allocated, nothing to do") + return nil + } + + claim = claim.DeepCopy() + if !ctrl.hasFinalizer(claim) { + // Set finalizer before doing anything. We continue with the updated claim. + logger.V(5).Info("Adding finalizer") + claim.Finalizers = append(claim.Finalizers, ctrl.finalizer) + var err error + claim, err = ctrl.kubeClient.ResourceV1alpha1().ResourceClaims(claim.Namespace).Update(ctx, claim, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("add finalizer: %v", err) + } + ctrl.claimCache.Mutation(claim) + } + + logger.V(5).Info("Allocating") + allocation, err := ctrl.driver.Allocate(ctx, claim, claimParameters, class, classParameters, selectedNode) + if err != nil { + return fmt.Errorf("allocate: %v", err) + } + claim.Status.Allocation = allocation + claim.Status.DriverName = ctrl.name + if selectedUser != nil { + claim.Status.ReservedFor = append(claim.Status.ReservedFor, *selectedUser) + } + logger.V(6).Info("Updating claim after allocation", "claim", claim) + claim, err = ctrl.kubeClient.ResourceV1alpha1().ResourceClaims(claim.Namespace).UpdateStatus(ctx, claim, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("add allocation: %v", err) + } + ctrl.claimCache.Mutation(claim) + return nil +} + +func (ctrl *controller) checkPodClaim(ctx context.Context, pod *v1.Pod, podClaim v1.PodResourceClaim) (*ClaimAllocation, error) { + claimName := resourceclaim.Name(pod, &podClaim) + key := pod.Namespace + "/" + claimName + claim, err := ctrl.getCachedClaim(ctx, key) + if claim == nil || err != nil { + return nil, err + } + if podClaim.Source.ResourceClaimTemplateName != nil { + if err := resourceclaim.IsForPod(pod, claim); err != nil { + return nil, err + } + } + if claim.Spec.AllocationMode != resourcev1alpha1.AllocationModeWaitForFirstConsumer { + // Nothing to do for it as part of pod scheduling. + return nil, nil + } + class, err := ctrl.rcLister.Get(claim.Spec.ResourceClassName) + if err != nil { + return nil, err + } + if class.DriverName != ctrl.name { + return nil, nil + } + // Check parameters. + claimParameters, classParameters, err := ctrl.getParameters(ctx, claim, class) + if err != nil { + return nil, err + } + return &ClaimAllocation{ + PodClaimName: podClaim.Name, + Claim: claim, + Class: class, + ClaimParameters: claimParameters, + ClassParameters: classParameters, + }, nil +} + +// syncClaim determines which next action may be needed for a PodScheduling object +// and does it. +func (ctrl *controller) syncPodScheduling(ctx context.Context, podScheduling *resourcev1alpha1.PodScheduling) error { + logger := klog.FromContext(ctx) + + // Ignore deleted objects. + if podScheduling.DeletionTimestamp != nil { + logger.V(5).Info("PodScheduling marked for deletion") + return nil + } + + if podScheduling.Spec.SelectedNode == "" && + len(podScheduling.Spec.PotentialNodes) == 0 { + // Nothing to do? Shouldn't occur. + logger.V(5).Info("Waiting for scheduler to set fields") + return nil + } + + // Check pod. + // TODO (?): use an informer - only useful when many (most?) pods have claims + // TODO (?): let the scheduler copy all claim names + UIDs into PodScheduling - then we don't need the pod + pod, err := ctrl.kubeClient.CoreV1().Pods(podScheduling.Namespace).Get(ctx, podScheduling.Name, metav1.GetOptions{}) + if err != nil { + return err + } + if pod.DeletionTimestamp != nil { + logger.V(5).Info("Pod marked for deletion") + return nil + } + + // Still the owner? + if !metav1.IsControlledBy(podScheduling, pod) { + // Must be obsolete object, do nothing for it. + logger.V(5).Info("Pod not owner, PodScheduling is obsolete") + return nil + } + + // Find all pending claims that are owned by us. We bail out if any of the pre-requisites + // for pod scheduling (claims exist, classes exist, parameters exist) are not met. + // The scheduler will do the same, except for checking parameters, so usually + // everything should be ready once the PodScheduling object exists. + var claims claimAllocations + for _, podClaim := range pod.Spec.ResourceClaims { + delayed, err := ctrl.checkPodClaim(ctx, pod, podClaim) + if err != nil { + return fmt.Errorf("pod claim %s: %v", podClaim.Name, err) + } + if delayed == nil { + // Nothing to do for it. This can change, so keep checking. + continue + } + claims = append(claims, delayed) + } + if len(claims) == 0 { + logger.V(5).Info("Found no pending pod claims") + return errPeriodic + } + + // Check current resource availability *before* triggering the + // allocations. If we find that any of the claims cannot be allocated + // for the selected node, we don't need to try for the others either + // and shouldn't, because those allocations might have to be undone to + // pick a better node. If we don't need to allocate now, then we'll + // simply report back the gather information. + if len(podScheduling.Spec.PotentialNodes) > 0 { + if err := ctrl.driver.UnsuitableNodes(ctx, pod, claims, podScheduling.Spec.PotentialNodes); err != nil { + return fmt.Errorf("checking potential nodes: %v", err) + } + } + selectedNode := podScheduling.Spec.SelectedNode + logger.V(5).Info("pending pod claims", "claims", claims, "selectedNode", selectedNode) + if selectedNode != "" { + unsuitable := false + for _, delayed := range claims { + if hasString(delayed.UnsuitableNodes, selectedNode) { + unsuitable = true + break + } + } + + if unsuitable { + logger.V(2).Info("skipping allocation for unsuitable selected node", "node", selectedNode) + } else { + logger.V(2).Info("allocation for selected node", "node", selectedNode) + selectedUser := &resourcev1alpha1.ResourceClaimConsumerReference{ + Resource: "pods", + Name: pod.Name, + UID: pod.UID, + } + for _, delayed := range claims { + if err := ctrl.allocateClaim(ctx, delayed.Claim, delayed.ClaimParameters, delayed.Class, delayed.ClassParameters, selectedNode, selectedUser); err != nil { + return fmt.Errorf("allocation of pod claim %s failed: %v", delayed.PodClaimName, err) + } + } + } + } + + // Now update unsuitable nodes. This is useful information for the scheduler even if + // we managed to allocate because we might have to undo that. + // TODO: replace with patching the array. We can do that without race conditions + // because each driver is responsible for its own entries. + modified := false + podScheduling = podScheduling.DeepCopy() + for _, delayed := range claims { + i := findClaim(podScheduling.Status.ResourceClaims, delayed.PodClaimName) + if i < 0 { + // Add new entry. + podScheduling.Status.ResourceClaims = append(podScheduling.Status.ResourceClaims, + resourcev1alpha1.ResourceClaimSchedulingStatus{ + Name: delayed.PodClaimName, + UnsuitableNodes: delayed.UnsuitableNodes, + }) + modified = true + } else if stringsDiffer(podScheduling.Status.ResourceClaims[i].UnsuitableNodes, delayed.UnsuitableNodes) { + // Update existing entry. + podScheduling.Status.ResourceClaims[i].UnsuitableNodes = delayed.UnsuitableNodes + modified = true + } + } + if modified { + logger.V(6).Info("Updating pod scheduling with modified unsuitable nodes", "podScheduling", podScheduling) + if _, err := ctrl.kubeClient.ResourceV1alpha1().PodSchedulings(podScheduling.Namespace).UpdateStatus(ctx, podScheduling, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("update unsuitable node status: %v", err) + } + } + + // We must keep the object in our queue and keep updating the + // UnsuitableNodes fields. + return errPeriodic +} + +type claimAllocations []*ClaimAllocation + +// MarshalLog replaces the pointers with the actual structs because +// we care about the content, not the pointer values. +func (claims claimAllocations) MarshalLog() interface{} { + content := make([]ClaimAllocation, 0, len(claims)) + for _, claim := range claims { + content = append(content, *claim) + } + return content +} + +var _ logr.Marshaler = claimAllocations{} + +// findClaim returns the index of the specified pod claim, -1 if not found. +func findClaim(claims []resourcev1alpha1.ResourceClaimSchedulingStatus, podClaimName string) int { + for i := range claims { + if claims[i].Name == podClaimName { + return i + } + } + return -1 +} + +// hasString checks for a string in a slice. +func hasString(strings []string, str string) bool { + for _, s := range strings { + if s == str { + return true + } + } + return false +} + +// stringsDiffer does a strict comparison of two string arrays, order of entries matters. +func stringsDiffer(a, b []string) bool { + if len(a) != len(b) { + return true + } + for i := range a { + if a[i] != b[i] { + return true + } + } + return false +} + +// hasFinalizer checks if the claim has the finalizer of the driver. +func (ctrl *controller) hasFinalizer(claim *resourcev1alpha1.ResourceClaim) bool { + for _, finalizer := range claim.Finalizers { + if finalizer == ctrl.finalizer { + return true + } + } + return false +} + +// removeFinalizer creates a new slice without the finalizer of the driver. +func (ctrl *controller) removeFinalizer(in []string) []string { + out := make([]string, 0, len(in)) + for _, finalizer := range in { + if finalizer != ctrl.finalizer { + out = append(out, finalizer) + } + } + if len(out) == 0 { + return nil + } + return out +} + +// prettyPrint formats arbitrary objects as JSON or, if that fails, with Sprintf. +func prettyPrint(obj interface{}) string { + buffer, err := json.Marshal(obj) + if err != nil { + return fmt.Sprintf("%s", obj) + } + return string(buffer) +} diff --git a/staging/src/k8s.io/dynamic-resource-allocation/controller/controller_test.go b/staging/src/k8s.io/dynamic-resource-allocation/controller/controller_test.go new file mode 100644 index 00000000000..d9b6a3eb586 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/controller/controller_test.go @@ -0,0 +1,652 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controller + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + corev1 "k8s.io/api/core/v1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/fake" + "k8s.io/client-go/tools/cache" + "k8s.io/klog/v2/ktesting" + _ "k8s.io/klog/v2/ktesting/init" +) + +func TestController(t *testing.T) { + claimKey := "claim:default/claim" + claimName := "claim" + claimNamespace := "default" + driverName := "mock-driver" + className := "mock-class" + otherDriverName := "other-driver" + otherClassName := "other-class" + ourFinalizer := driverName + "/deletion-protection" + otherFinalizer := otherDriverName + "/deletion-protection" + classes := []*resourcev1alpha1.ResourceClass{ + createClass(className, driverName), + createClass(otherClassName, otherDriverName), + } + claim := createClaim(claimName, claimNamespace, className) + otherClaim := createClaim(claimName, claimNamespace, otherClassName) + delayedClaim := claim.DeepCopy() + delayedClaim.Spec.AllocationMode = resourcev1alpha1.AllocationModeWaitForFirstConsumer + podName := "pod" + podKey := "podscheduling:default/pod" + pod := createPod(podName, claimNamespace, nil) + podClaimName := "my-pod-claim" + podScheduling := createPodScheduling(pod) + podWithClaim := createPod(podName, claimNamespace, map[string]string{podClaimName: claimName}) + nodeName := "worker" + otherNodeName := "worker-2" + unsuitableNodes := []string{otherNodeName} + potentialNodes := []string{nodeName, otherNodeName} + withDeletionTimestamp := func(claim *resourcev1alpha1.ResourceClaim) *resourcev1alpha1.ResourceClaim { + var deleted metav1.Time + claim = claim.DeepCopy() + claim.DeletionTimestamp = &deleted + return claim + } + withReservedFor := func(claim *resourcev1alpha1.ResourceClaim, pod *corev1.Pod) *resourcev1alpha1.ResourceClaim { + claim = claim.DeepCopy() + claim.Status.ReservedFor = append(claim.Status.ReservedFor, resourcev1alpha1.ResourceClaimConsumerReference{ + Resource: "pods", + Name: pod.Name, + UID: pod.UID, + }) + return claim + } + withFinalizer := func(claim *resourcev1alpha1.ResourceClaim, finalizer string) *resourcev1alpha1.ResourceClaim { + claim = claim.DeepCopy() + claim.Finalizers = append(claim.Finalizers, finalizer) + return claim + } + allocation := resourcev1alpha1.AllocationResult{} + withAllocate := func(claim *resourcev1alpha1.ResourceClaim) *resourcev1alpha1.ResourceClaim { + // Any allocated claim must have our finalizer. + claim = withFinalizer(claim, ourFinalizer) + claim.Status.Allocation = &allocation + claim.Status.DriverName = driverName + return claim + } + withDeallocate := func(claim *resourcev1alpha1.ResourceClaim) *resourcev1alpha1.ResourceClaim { + claim.Status.DeallocationRequested = true + return claim + } + withSelectedNode := func(podScheduling *resourcev1alpha1.PodScheduling) *resourcev1alpha1.PodScheduling { + podScheduling = podScheduling.DeepCopy() + podScheduling.Spec.SelectedNode = nodeName + return podScheduling + } + withUnsuitableNodes := func(podScheduling *resourcev1alpha1.PodScheduling) *resourcev1alpha1.PodScheduling { + podScheduling = podScheduling.DeepCopy() + podScheduling.Status.ResourceClaims = append(podScheduling.Status.ResourceClaims, + resourcev1alpha1.ResourceClaimSchedulingStatus{Name: podClaimName, UnsuitableNodes: unsuitableNodes}, + ) + return podScheduling + } + withPotentialNodes := func(podScheduling *resourcev1alpha1.PodScheduling) *resourcev1alpha1.PodScheduling { + podScheduling = podScheduling.DeepCopy() + podScheduling.Spec.PotentialNodes = potentialNodes + return podScheduling + } + + var m mockDriver + + for name, test := range map[string]struct { + key string + driver mockDriver + classes []*resourcev1alpha1.ResourceClass + pod *corev1.Pod + podScheduling, expectedPodScheduling *resourcev1alpha1.PodScheduling + claim, expectedClaim *resourcev1alpha1.ResourceClaim + expectedError string + }{ + "invalid-key": { + key: "claim:x/y/z", + expectedError: `unexpected key format: "x/y/z"`, + }, + "not-found": { + key: "claim:default/claim", + }, + "wrong-driver": { + key: claimKey, + classes: classes, + claim: otherClaim, + expectedClaim: otherClaim, + expectedError: errRequeue.Error(), // class might change + }, + // Immediate allocation: + // deletion time stamp set, our finalizer set, not allocated -> remove finalizer + "immediate-deleted-finalizer-removal": { + key: claimKey, + classes: classes, + claim: withFinalizer(withDeletionTimestamp(claim), ourFinalizer), + driver: m.expectDeallocate(map[string]error{claimName: nil}), + expectedClaim: withDeletionTimestamp(claim), + }, + // deletion time stamp set, our finalizer set, not allocated, stopping fails -> requeue + "immediate-deleted-finalizer-stop-failure": { + key: claimKey, + classes: classes, + claim: withFinalizer(withDeletionTimestamp(claim), ourFinalizer), + driver: m.expectDeallocate(map[string]error{claimName: errors.New("fake error")}), + expectedClaim: withFinalizer(withDeletionTimestamp(claim), ourFinalizer), + expectedError: "stop allocation: fake error", + }, + // deletion time stamp set, other finalizer set, not allocated -> do nothing + "immediate-deleted-finalizer-no-removal": { + key: claimKey, + classes: classes, + claim: withFinalizer(withDeletionTimestamp(claim), otherFinalizer), + expectedClaim: withFinalizer(withDeletionTimestamp(claim), otherFinalizer), + }, + // deletion time stamp set, finalizer set, allocated -> deallocate + "immediate-deleted-allocated": { + key: claimKey, + classes: classes, + claim: withAllocate(withDeletionTimestamp(claim)), + driver: m.expectDeallocate(map[string]error{claimName: nil}), + expectedClaim: withDeletionTimestamp(claim), + }, + // deletion time stamp set, finalizer set, allocated, deallocation fails -> requeue + "immediate-deleted-deallocate-failure": { + key: claimKey, + classes: classes, + claim: withAllocate(withDeletionTimestamp(claim)), + driver: m.expectDeallocate(map[string]error{claimName: errors.New("fake error")}), + expectedClaim: withAllocate(withDeletionTimestamp(claim)), + expectedError: "deallocate: fake error", + }, + // deletion time stamp set, finalizer not set -> do nothing + "immediate-deleted-no-finalizer": { + key: claimKey, + classes: classes, + claim: withDeletionTimestamp(claim), + expectedClaim: withDeletionTimestamp(claim), + }, + // not deleted, not allocated, no finalizer -> add finalizer, allocate + "immediate-do-allocation": { + key: claimKey, + classes: classes, + claim: claim, + driver: m.expectClassParameters(map[string]interface{}{className: 1}). + expectClaimParameters(map[string]interface{}{claimName: 2}). + expectAllocate(map[string]allocate{claimName: {allocResult: &allocation, allocErr: nil}}), + expectedClaim: withAllocate(claim), + }, + // not deleted, not allocated, finalizer -> allocate + "immediate-continue-allocation": { + key: claimKey, + classes: classes, + claim: withFinalizer(claim, ourFinalizer), + driver: m.expectClassParameters(map[string]interface{}{className: 1}). + expectClaimParameters(map[string]interface{}{claimName: 2}). + expectAllocate(map[string]allocate{claimName: {allocResult: &allocation, allocErr: nil}}), + expectedClaim: withAllocate(claim), + }, + // not deleted, not allocated, finalizer, fail allocation -> requeue + "immediate-fail-allocation": { + key: claimKey, + classes: classes, + claim: withFinalizer(claim, ourFinalizer), + driver: m.expectClassParameters(map[string]interface{}{className: 1}). + expectClaimParameters(map[string]interface{}{claimName: 2}). + expectAllocate(map[string]allocate{claimName: {allocErr: errors.New("fake error")}}), + expectedClaim: withFinalizer(claim, ourFinalizer), + expectedError: "allocate: fake error", + }, + // not deleted, allocated -> do nothing + "immediate-allocated-nop": { + key: claimKey, + classes: classes, + claim: withAllocate(claim), + expectedClaim: withAllocate(claim), + }, + + // not deleted, reallocate -> deallocate + "immediate-allocated-reallocate": { + key: claimKey, + classes: classes, + claim: withDeallocate(withAllocate(claim)), + driver: m.expectDeallocate(map[string]error{claimName: nil}), + expectedClaim: claim, + }, + + // not deleted, reallocate, deallocate failure -> requeue + "immediate-allocated-fail-deallocation-during-reallocate": { + key: claimKey, + classes: classes, + claim: withDeallocate(withAllocate(claim)), + driver: m.expectDeallocate(map[string]error{claimName: errors.New("fake error")}), + expectedClaim: withDeallocate(withAllocate(claim)), + expectedError: "deallocate: fake error", + }, + + // Delayed allocation is similar in some cases, but not quite + // the same. + // deletion time stamp set, our finalizer set, not allocated -> remove finalizer + "delayed-deleted-finalizer-removal": { + key: claimKey, + classes: classes, + claim: withFinalizer(withDeletionTimestamp(delayedClaim), ourFinalizer), + driver: m.expectDeallocate(map[string]error{claimName: nil}), + expectedClaim: withDeletionTimestamp(delayedClaim), + }, + // deletion time stamp set, our finalizer set, not allocated, stopping fails -> requeue + "delayed-deleted-finalizer-stop-failure": { + key: claimKey, + classes: classes, + claim: withFinalizer(withDeletionTimestamp(delayedClaim), ourFinalizer), + driver: m.expectDeallocate(map[string]error{claimName: errors.New("fake error")}), + expectedClaim: withFinalizer(withDeletionTimestamp(delayedClaim), ourFinalizer), + expectedError: "stop allocation: fake error", + }, + // deletion time stamp set, other finalizer set, not allocated -> do nothing + "delayed-deleted-finalizer-no-removal": { + key: claimKey, + classes: classes, + claim: withFinalizer(withDeletionTimestamp(delayedClaim), otherFinalizer), + expectedClaim: withFinalizer(withDeletionTimestamp(delayedClaim), otherFinalizer), + }, + // deletion time stamp set, finalizer set, allocated -> deallocate + "delayed-deleted-allocated": { + key: claimKey, + classes: classes, + claim: withAllocate(withDeletionTimestamp(delayedClaim)), + driver: m.expectDeallocate(map[string]error{claimName: nil}), + expectedClaim: withDeletionTimestamp(delayedClaim), + }, + // deletion time stamp set, finalizer set, allocated, deallocation fails -> requeue + "delayed-deleted-deallocate-failure": { + key: claimKey, + classes: classes, + claim: withAllocate(withDeletionTimestamp(delayedClaim)), + driver: m.expectDeallocate(map[string]error{claimName: errors.New("fake error")}), + expectedClaim: withAllocate(withDeletionTimestamp(delayedClaim)), + expectedError: "deallocate: fake error", + }, + // deletion time stamp set, finalizer not set -> do nothing + "delayed-deleted-no-finalizer": { + key: claimKey, + classes: classes, + claim: withDeletionTimestamp(delayedClaim), + expectedClaim: withDeletionTimestamp(delayedClaim), + }, + // waiting for first consumer -> do nothing + "delayed-pending": { + key: claimKey, + classes: classes, + claim: delayedClaim, + expectedClaim: delayedClaim, + }, + + // pod with no claims -> shouldn't occur, check again anyway + "pod-nop": { + key: podKey, + pod: pod, + podScheduling: withSelectedNode(podScheduling), + expectedPodScheduling: withSelectedNode(podScheduling), + expectedError: errPeriodic.Error(), + }, + + // pod with immediate allocation and selected node -> shouldn't occur, check again in case that claim changes + "pod-immediate": { + key: podKey, + claim: claim, + expectedClaim: claim, + pod: podWithClaim, + podScheduling: withSelectedNode(podScheduling), + expectedPodScheduling: withSelectedNode(podScheduling), + expectedError: errPeriodic.Error(), + }, + + // pod with delayed allocation, no potential nodes -> shouldn't occur + "pod-delayed-no-nodes": { + key: podKey, + classes: classes, + claim: delayedClaim, + expectedClaim: delayedClaim, + pod: podWithClaim, + podScheduling: podScheduling, + expectedPodScheduling: podScheduling, + }, + + // pod with delayed allocation, potential nodes -> provide unsuitable nodes + "pod-delayed-info": { + key: podKey, + classes: classes, + claim: delayedClaim, + expectedClaim: delayedClaim, + pod: podWithClaim, + podScheduling: withPotentialNodes(podScheduling), + driver: m.expectClassParameters(map[string]interface{}{className: 1}). + expectClaimParameters(map[string]interface{}{claimName: 2}). + expectUnsuitableNodes(map[string][]string{podClaimName: unsuitableNodes}, nil), + expectedPodScheduling: withUnsuitableNodes(withPotentialNodes(podScheduling)), + expectedError: errPeriodic.Error(), + }, + + // pod with delayed allocation, potential nodes, selected node, missing class -> failure + "pod-delayed-missing-class": { + key: podKey, + claim: delayedClaim, + expectedClaim: delayedClaim, + pod: podWithClaim, + podScheduling: withSelectedNode(withPotentialNodes(podScheduling)), + expectedPodScheduling: withSelectedNode(withPotentialNodes(podScheduling)), + expectedError: `pod claim my-pod-claim: resourceclass.resource.k8s.io "mock-class" not found`, + }, + + // pod with delayed allocation, potential nodes, selected node -> allocate + "pod-delayed-allocate": { + key: podKey, + classes: classes, + claim: delayedClaim, + expectedClaim: withReservedFor(withAllocate(delayedClaim), pod), + pod: podWithClaim, + podScheduling: withSelectedNode(withPotentialNodes(podScheduling)), + driver: m.expectClassParameters(map[string]interface{}{className: 1}). + expectClaimParameters(map[string]interface{}{claimName: 2}). + expectUnsuitableNodes(map[string][]string{podClaimName: unsuitableNodes}, nil). + expectAllocate(map[string]allocate{claimName: {allocResult: &allocation, selectedNode: nodeName, allocErr: nil}}), + expectedPodScheduling: withUnsuitableNodes(withSelectedNode(withPotentialNodes(podScheduling))), + expectedError: errPeriodic.Error(), + }, + } { + t.Run(name, func(t *testing.T) { + _, ctx := ktesting.NewTestContext(t) + ctx, cancel := context.WithCancel(ctx) + + initialObjects := []runtime.Object{} + for _, class := range test.classes { + initialObjects = append(initialObjects, class) + } + if test.pod != nil { + initialObjects = append(initialObjects, test.pod) + } + if test.podScheduling != nil { + initialObjects = append(initialObjects, test.podScheduling) + } + if test.claim != nil { + initialObjects = append(initialObjects, test.claim) + } + kubeClient, informerFactory := fakeK8s(initialObjects) + rcInformer := informerFactory.Resource().V1alpha1().ResourceClasses() + claimInformer := informerFactory.Resource().V1alpha1().ResourceClaims() + podInformer := informerFactory.Core().V1().Pods() + podSchedulingInformer := informerFactory.Resource().V1alpha1().PodSchedulings() + // Order is important: on function exit, we first must + // cancel, then wait (last-in-first-out). + defer informerFactory.Shutdown() + defer cancel() + + for _, obj := range initialObjects { + switch obj.(type) { + case *resourcev1alpha1.ResourceClass: + require.NoError(t, rcInformer.Informer().GetStore().Add(obj), "add resource class") + case *resourcev1alpha1.ResourceClaim: + require.NoError(t, claimInformer.Informer().GetStore().Add(obj), "add resource claim") + case *corev1.Pod: + require.NoError(t, podInformer.Informer().GetStore().Add(obj), "add pod") + case *resourcev1alpha1.PodScheduling: + require.NoError(t, podSchedulingInformer.Informer().GetStore().Add(obj), "add pod scheduling") + default: + t.Fatalf("unknown initialObject type: %+v", obj) + } + } + + driver := test.driver + driver.t = t + + ctrl := New(ctx, driverName, driver, kubeClient, informerFactory) + informerFactory.Start(ctx.Done()) + if !cache.WaitForCacheSync(ctx.Done(), + informerFactory.Resource().V1alpha1().ResourceClasses().Informer().HasSynced, + informerFactory.Resource().V1alpha1().ResourceClaims().Informer().HasSynced, + informerFactory.Resource().V1alpha1().PodSchedulings().Informer().HasSynced, + ) { + t.Fatal("could not sync caches") + } + _, err := ctrl.(*controller).syncKey(ctx, test.key) + if err != nil && test.expectedError == "" { + t.Fatalf("unexpected error: %v", err) + } + if err == nil && test.expectedError != "" { + t.Fatalf("did not get expected error %q", test.expectedError) + } + if err != nil && err.Error() != test.expectedError { + t.Fatalf("expected error %q, got %q", test.expectedError, err.Error()) + } + claims, err := kubeClient.ResourceV1alpha1().ResourceClaims("").List(ctx, metav1.ListOptions{}) + require.NoError(t, err, "list claims") + var expectedClaims []resourcev1alpha1.ResourceClaim + if test.expectedClaim != nil { + expectedClaims = append(expectedClaims, *test.expectedClaim) + } + assert.Equal(t, expectedClaims, claims.Items) + + podSchedulings, err := kubeClient.ResourceV1alpha1().PodSchedulings("").List(ctx, metav1.ListOptions{}) + require.NoError(t, err, "list pod schedulings") + var expectedPodSchedulings []resourcev1alpha1.PodScheduling + if test.expectedPodScheduling != nil { + expectedPodSchedulings = append(expectedPodSchedulings, *test.expectedPodScheduling) + } + assert.Equal(t, expectedPodSchedulings, podSchedulings.Items) + + // TODO: add testing of events. + // Right now, client-go/tools/record/event.go:267 fails during unit testing with + // request namespace does not match object namespace, request: "" object: "default", + }) + } +} + +type mockDriver struct { + t *testing.T + + // TODO: change this so that the mock driver expects calls in a certain order + // and fails when the next call isn't the expected one or calls didn't happen + classParameters map[string]interface{} + claimParameters map[string]interface{} + allocate map[string]allocate + deallocate map[string]error + unsuitableNodes map[string][]string + unsuitableNodesError error +} + +type allocate struct { + selectedNode string + allocResult *resourcev1alpha1.AllocationResult + allocErr error +} + +func (m mockDriver) expectClassParameters(expected map[string]interface{}) mockDriver { + m.classParameters = expected + return m +} + +func (m mockDriver) expectClaimParameters(expected map[string]interface{}) mockDriver { + m.claimParameters = expected + return m +} + +func (m mockDriver) expectAllocate(expected map[string]allocate) mockDriver { + m.allocate = expected + return m +} + +func (m mockDriver) expectDeallocate(expected map[string]error) mockDriver { + m.deallocate = expected + return m +} + +func (m mockDriver) expectUnsuitableNodes(expected map[string][]string, err error) mockDriver { + m.unsuitableNodes = expected + m.unsuitableNodesError = err + return m +} + +func (m mockDriver) GetClassParameters(ctx context.Context, class *resourcev1alpha1.ResourceClass) (interface{}, error) { + m.t.Logf("GetClassParameters(%s)", class) + result, ok := m.classParameters[class.Name] + if !ok { + m.t.Fatal("unexpected GetClassParameters call") + } + if err, ok := result.(error); ok { + return nil, err + } + return result, nil +} + +func (m mockDriver) GetClaimParameters(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, class *resourcev1alpha1.ResourceClass, classParameters interface{}) (interface{}, error) { + m.t.Logf("GetClaimParameters(%s)", claim) + result, ok := m.claimParameters[claim.Name] + if !ok { + m.t.Fatal("unexpected GetClaimParameters call") + } + if err, ok := result.(error); ok { + return nil, err + } + return result, nil +} + +func (m mockDriver) Allocate(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, claimParameters interface{}, class *resourcev1alpha1.ResourceClass, classParameters interface{}, selectedNode string) (*resourcev1alpha1.AllocationResult, error) { + m.t.Logf("Allocate(%s)", claim) + allocate, ok := m.allocate[claim.Name] + if !ok { + m.t.Fatal("unexpected Allocate call") + } + assert.Equal(m.t, allocate.selectedNode, selectedNode, "selected node") + return allocate.allocResult, allocate.allocErr +} + +func (m mockDriver) Deallocate(ctx context.Context, claim *resourcev1alpha1.ResourceClaim) error { + m.t.Logf("Deallocate(%s)", claim) + err, ok := m.deallocate[claim.Name] + if !ok { + m.t.Fatal("unexpected Deallocate call") + } + return err +} + +func (m mockDriver) UnsuitableNodes(ctx context.Context, pod *corev1.Pod, claims []*ClaimAllocation, potentialNodes []string) error { + m.t.Logf("UnsuitableNodes(%s, %v, %v)", pod, claims, potentialNodes) + if len(m.unsuitableNodes) == 0 { + m.t.Fatal("unexpected UnsuitableNodes call") + } + if m.unsuitableNodesError != nil { + return m.unsuitableNodesError + } + found := map[string]bool{} + for _, delayed := range claims { + unsuitableNodes, ok := m.unsuitableNodes[delayed.PodClaimName] + if !ok { + m.t.Errorf("unexpected pod claim: %s", delayed.PodClaimName) + } + delayed.UnsuitableNodes = unsuitableNodes + found[delayed.PodClaimName] = true + } + for expectedName := range m.unsuitableNodes { + if !found[expectedName] { + m.t.Errorf("pod claim %s not in actual claims list", expectedName) + } + } + return nil +} + +func createClass(className, driverName string) *resourcev1alpha1.ResourceClass { + return &resourcev1alpha1.ResourceClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: className, + }, + DriverName: driverName, + } +} + +func createClaim(claimName, claimNamespace, className string) *resourcev1alpha1.ResourceClaim { + return &resourcev1alpha1.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: claimName, + Namespace: claimNamespace, + }, + Spec: resourcev1alpha1.ResourceClaimSpec{ + ResourceClassName: className, + AllocationMode: resourcev1alpha1.AllocationModeImmediate, + }, + } +} + +func createPod(podName, podNamespace string, claims map[string]string) *corev1.Pod { + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: podNamespace, + UID: "1234", + }, + } + for podClaimName, claimName := range claims { + pod.Spec.ResourceClaims = append(pod.Spec.ResourceClaims, + corev1.PodResourceClaim{ + Name: podClaimName, + Source: corev1.ClaimSource{ + ResourceClaimName: &claimName, + }, + }, + ) + } + return pod +} + +func createPodScheduling(pod *corev1.Pod) *resourcev1alpha1.PodScheduling { + controller := true + return &resourcev1alpha1.PodScheduling{ + ObjectMeta: metav1.ObjectMeta{ + Name: pod.Name, + Namespace: pod.Namespace, + OwnerReferences: []metav1.OwnerReference{ + { + Name: pod.Name, + Controller: &controller, + UID: pod.UID, + }, + }, + }, + } +} + +func fakeK8s(objs []runtime.Object) (kubernetes.Interface, informers.SharedInformerFactory) { + // This is a very simple replacement for a real apiserver. For example, + // it doesn't do defaulting and accepts updates to the status in normal + // Update calls. Therefore this test does not catch when we use Update + // instead of UpdateStatus. Reactors could be used to catch that, but + // that seems overkill because E2E tests will find that. + // + // Interactions with the fake apiserver also never fail. TODO: + // simulate update errors. + client := fake.NewSimpleClientset(objs...) + informerFactory := informers.NewSharedInformerFactory(client, 0) + return client, informerFactory +} diff --git a/staging/src/k8s.io/dynamic-resource-allocation/doc.go b/staging/src/k8s.io/dynamic-resource-allocation/doc.go new file mode 100644 index 00000000000..0578424ad86 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package dynamicresourceallocation contains helper packages for the dynamic +// resource allocation feature. +package dynamicresourceallocation // import "k8s.io/dynamic-resource-allocation" diff --git a/staging/src/k8s.io/dynamic-resource-allocation/go.mod b/staging/src/k8s.io/dynamic-resource-allocation/go.mod new file mode 100644 index 00000000000..dd039c2bdbf --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/go.mod @@ -0,0 +1,65 @@ +// This is a generated file. Do not edit directly. + +module k8s.io/dynamic-resource-allocation + +go 1.19 + +require ( + github.com/go-logr/logr v1.2.3 + github.com/google/go-cmp v0.5.9 + github.com/stretchr/testify v1.8.0 + google.golang.org/grpc v1.49.0 + k8s.io/api v0.0.0 + k8s.io/apimachinery v0.0.0 + k8s.io/client-go v0.0.0 + k8s.io/klog/v2 v2.80.1 + k8s.io/kubelet v0.0.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/evanphx/json-patch v4.12.0+incompatible // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/swag v0.19.14 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/gofuzz v1.1.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mailru/easyjson v0.7.6 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/net v0.1.1-0.20221027164007-c63010009c80 // indirect + golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect + golang.org/x/sys v0.1.0 // indirect + golang.org/x/term v0.1.0 // indirect + golang.org/x/text v0.4.0 // indirect + golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect + k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) + +replace ( + k8s.io/api => ../api + k8s.io/apimachinery => ../apimachinery + k8s.io/client-go => ../client-go + k8s.io/component-base => ../component-base + k8s.io/dynamic-resource-allocation => ../dynamic-resource-allocation + k8s.io/kubelet => ../kubelet +) diff --git a/staging/src/k8s.io/dynamic-resource-allocation/go.sum b/staging/src/k8s.io/dynamic-resource-allocation/go.sum new file mode 100644 index 00000000000..6211f340ff7 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/go.sum @@ -0,0 +1,513 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs= +github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.1.1-0.20221027164007-c63010009c80 h1:CtRWmqbiPSOXwJV1JoY7pWiTx2xzVKQ813bvU+Y/9jI= +golang.org/x/net v0.1.1-0.20221027164007-c63010009c80/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d h1:0Smp/HP1OH4Rvhe+4B8nWGERtlqAGSftbSbbmm45oFs= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/doc.go b/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/doc.go new file mode 100644 index 00000000000..cdc33100a3f --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package kubeletplugin provides helper functions for running a dynamic +// resource allocation kubelet plugin. +package kubeletplugin diff --git a/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/draplugin.go b/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/draplugin.go new file mode 100644 index 00000000000..cfe1428b9f3 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/draplugin.go @@ -0,0 +1,236 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubeletplugin + +import ( + "errors" + "fmt" + "net" + + "google.golang.org/grpc" + "k8s.io/klog/v2" + + drapbv1 "k8s.io/kubelet/pkg/apis/dra/v1alpha1" + registerapi "k8s.io/kubelet/pkg/apis/pluginregistration/v1" +) + +// DRAPlugin gets returned by Start and defines the public API of the generic +// dynamic resource allocation plugin. +type DRAPlugin interface { + // Stop ensures that all spawned goroutines are stopped and frees + // resources. + Stop() + + // RegistrationStatus returns the result of registration, nil if none + // received yet. + RegistrationStatus() *registerapi.RegistrationStatus + + // This unexported method ensures that we can modify the interface + // without causing an API break of the package + // (https://pkg.go.dev/golang.org/x/exp/apidiff#section-readme). + internal() +} + +// Option implements the functional options pattern for Start. +type Option func(o *options) error + +// DriverName defines the driver name for the dynamic resource allocation driver. +// Must be set. +func DriverName(driverName string) Option { + return func(o *options) error { + o.driverName = driverName + return nil + } +} + +// Logger overrides the default klog.Background logger. +func Logger(logger klog.Logger) Option { + return func(o *options) error { + o.logger = logger + return nil + } +} + +// GRPCVerbosity sets the verbosity for logging gRPC calls. Default is 4. A negative +// value disables logging. +func GRPCVerbosity(level int) Option { + return func(o *options) error { + o.grpcVerbosity = level + return nil + } +} + +// RegistrarSocketPath sets the file path for a Unix domain socket. +// If RegistrarListener is not used, then Start will remove +// a file at that path, should one exist, and creates a socket +// itself. Otherwise it uses the provided listener and only +// removes the socket at the specified path during shutdown. +// +// At least one of these two options is required. +func RegistrarSocketPath(path string) Option { + return func(o *options) error { + o.pluginRegistrationEndpoint.path = path + return nil + } +} + +// RegistrarListener sets an already created listener for the plugin +// registrarion API. Can be combined with RegistrarSocketPath. +// +// At least one of these two options is required. +func RegistrarListener(listener net.Listener) Option { + return func(o *options) error { + o.pluginRegistrationEndpoint.listener = listener + return nil + } +} + +// PluginSocketPath sets the file path for a Unix domain socket. +// If PluginListener is not used, then Start will remove +// a file at that path, should one exist, and creates a socket +// itself. Otherwise it uses the provided listener and only +// removes the socket at the specified path during shutdown. +// +// At least one of these two options is required. +func PluginSocketPath(path string) Option { + return func(o *options) error { + o.draEndpoint.path = path + return nil + } +} + +// PluginListener sets an already created listener for the dynamic resource +// allocation plugin API. Can be combined with PluginSocketPath. +// +// At least one of these two options is required. +func PluginListener(listener net.Listener) Option { + return func(o *options) error { + o.draEndpoint.listener = listener + return nil + } +} + +// KubeletPluginSocketPath defines how kubelet will connect to the dynamic +// resource allocation plugin. This corresponds to PluginSocketPath, except +// that PluginSocketPath defines the path in the filesystem of the caller and +// KubeletPluginSocketPath in the filesystem of kubelet. +func KubeletPluginSocketPath(path string) Option { + return func(o *options) error { + o.draAddress = path + return nil + } +} + +// GRPCInterceptor is called for each incoming gRPC method call. +func GRPCInterceptor(interceptor grpc.UnaryServerInterceptor) Option { + return func(o *options) error { + o.interceptor = interceptor + return nil + } +} + +type options struct { + logger klog.Logger + grpcVerbosity int + driverName string + draEndpoint endpoint + draAddress string + pluginRegistrationEndpoint endpoint + interceptor grpc.UnaryServerInterceptor +} + +// draPlugin combines the kubelet registration service and the DRA node plugin +// service. +type draPlugin struct { + registrar *nodeRegistrar + plugin *grpcServer +} + +// Start sets up two gRPC servers (one for registration, one for the DRA node +// client). +func Start(nodeServer drapbv1.NodeServer, opts ...Option) (result DRAPlugin, finalErr error) { + d := &draPlugin{} + + o := options{ + logger: klog.Background(), + grpcVerbosity: 4, + } + for _, option := range opts { + if err := option(&o); err != nil { + return nil, err + } + } + + if o.driverName == "" { + return nil, errors.New("driver name must be set") + } + if o.draAddress == "" { + return nil, errors.New("DRA address must be set") + } + var emptyEndpoint endpoint + if o.draEndpoint == emptyEndpoint { + return nil, errors.New("a Unix domain socket path and/or listener must be set for the kubelet plugin") + } + if o.pluginRegistrationEndpoint == emptyEndpoint { + return nil, errors.New("a Unix domain socket path and/or listener must be set for the registrar") + } + + // Run the node plugin gRPC server first to ensure that it is ready. + plugin, err := startGRPCServer(klog.LoggerWithName(o.logger, "dra"), o.grpcVerbosity, o.interceptor, o.draEndpoint, func(grpcServer *grpc.Server) { + drapbv1.RegisterNodeServer(grpcServer, nodeServer) + }) + if err != nil { + return nil, fmt.Errorf("start node client: %v", err) + } + d.plugin = plugin + defer func() { + // Clean up if we didn't finish succcessfully. + if r := recover(); r != nil { + plugin.stop() + panic(r) + } + if finalErr != nil { + plugin.stop() + } + }() + + // Now make it available to kubelet. + registrar, err := startRegistrar(klog.LoggerWithName(o.logger, "registrar"), o.grpcVerbosity, o.interceptor, o.driverName, o.draAddress, o.pluginRegistrationEndpoint) + if err != nil { + return nil, fmt.Errorf("start registrar: %v", err) + } + d.registrar = registrar + + return d, nil +} + +func (d *draPlugin) Stop() { + if d == nil { + return + } + d.registrar.stop() + d.plugin.stop() +} + +func (d *draPlugin) RegistrationStatus() *registerapi.RegistrationStatus { + if d.registrar == nil { + return nil + } + return d.registrar.status +} + +func (d *draPlugin) internal() {} diff --git a/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/noderegistrar.go b/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/noderegistrar.go new file mode 100644 index 00000000000..1f37db22fe9 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/noderegistrar.go @@ -0,0 +1,60 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubeletplugin + +import ( + "fmt" + + "google.golang.org/grpc" + "k8s.io/klog/v2" + registerapi "k8s.io/kubelet/pkg/apis/pluginregistration/v1" +) + +type nodeRegistrar struct { + logger klog.Logger + registrationServer + server *grpcServer +} + +// startRegistrar returns a running instance. +func startRegistrar(logger klog.Logger, grpcVerbosity int, interceptor grpc.UnaryServerInterceptor, driverName string, endpoint string, pluginRegistrationEndpoint endpoint) (*nodeRegistrar, error) { + n := &nodeRegistrar{ + logger: logger, + registrationServer: registrationServer{ + driverName: driverName, + endpoint: endpoint, + supportedVersions: []string{"1.0.0"}, // TODO: is this correct? + }, + } + s, err := startGRPCServer(logger, grpcVerbosity, interceptor, pluginRegistrationEndpoint, func(grpcServer *grpc.Server) { + registerapi.RegisterRegistrationServer(grpcServer, n) + }) + if err != nil { + return nil, fmt.Errorf("start gRPC server: %v", err) + } + n.server = s + return n, nil +} + +// stop ensures that the registrar is not running anymore and cleans up all resources. +// It is idempotent and may be called with a nil pointer. +func (s *nodeRegistrar) stop() { + if s == nil { + return + } + s.server.stop() +} diff --git a/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/nonblockinggrpcserver.go b/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/nonblockinggrpcserver.go new file mode 100644 index 00000000000..16df39710de --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/nonblockinggrpcserver.go @@ -0,0 +1,151 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubeletplugin + +import ( + "context" + "fmt" + "net" + "os" + "sync" + "sync/atomic" + + "google.golang.org/grpc" + "k8s.io/klog/v2" +) + +type grpcServer struct { + logger klog.Logger + grpcVerbosity int + wg sync.WaitGroup + endpoint endpoint + server *grpc.Server + requestID int64 +} + +type registerService func(s *grpc.Server) + +// endpoint defines where to listen for incoming connections. +// The listener always gets closed when shutting down. +// +// If the listener is not set, a new listener for a Unix domain socket gets +// created at the path. +// +// If the path is non-empty, then the socket will get removed when shutting +// down, regardless of who created the listener. +type endpoint struct { + path string + listener net.Listener +} + +// startGRPCServer sets up the GRPC server on a Unix domain socket and spawns a goroutine +// which handles requests for arbitrary services. +func startGRPCServer(logger klog.Logger, grpcVerbosity int, interceptor grpc.UnaryServerInterceptor, endpoint endpoint, services ...registerService) (*grpcServer, error) { + s := &grpcServer{ + logger: logger, + endpoint: endpoint, + grpcVerbosity: grpcVerbosity, + } + + listener := endpoint.listener + if listener == nil { + // Remove any (probably stale) existing socket. + if err := os.Remove(endpoint.path); err != nil && !os.IsNotExist(err) { + return nil, fmt.Errorf("remove Unix domain socket: %v", err) + } + + // Now we can use the endpoint for listening. + l, err := net.Listen("unix", endpoint.path) + if err != nil { + return nil, fmt.Errorf("listen on %q: %v", endpoint.path, err) + } + listener = l + } + + // Run a gRPC server. It will close the listening socket when + // shutting down, so we don't need to do that. + var opts []grpc.ServerOption + var interceptors []grpc.UnaryServerInterceptor + if grpcVerbosity >= 0 { + interceptors = append(interceptors, s.interceptor) + } + if interceptor != nil { + interceptors = append(interceptors, interceptor) + } + if len(interceptors) >= 0 { + opts = append(opts, grpc.ChainUnaryInterceptor(interceptors...)) + } + s.server = grpc.NewServer(opts...) + for _, service := range services { + service(s.server) + } + s.wg.Add(1) + go func() { + defer s.wg.Done() + err := s.server.Serve(listener) + if err != nil { + logger.Error(err, "GRPC server failed") + } else { + logger.V(3).Info("GRPC server terminated gracefully") + } + }() + + logger.Info("GRPC server started") + return s, nil +} + +// interceptor is called for each request. It creates a logger with a unique, +// sequentially increasing request ID and adds that logger to the context. It +// also logs request and response. +func (s *grpcServer) interceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { + requestID := atomic.AddInt64(&s.requestID, 1) + logger := klog.LoggerWithValues(s.logger, "requestID", requestID) + ctx = klog.NewContext(ctx, logger) + logger.V(s.grpcVerbosity).Info("handling request", "request", req) + defer func() { + if r := recover(); r != nil { + logger.Error(nil, "handling request panicked", "panic", r, "request", req) + panic(r) + } + }() + resp, err = handler(ctx, req) + if err != nil { + logger.Error(err, "handling request failed", "request", req) + } else { + logger.V(s.grpcVerbosity).Info("handling request succeeded", "response", resp) + } + return +} + +// stop ensures that the server is not running anymore and cleans up all resources. +// It is idempotent and may be called with a nil pointer. +func (s *grpcServer) stop() { + if s == nil { + return + } + if s.server != nil { + s.server.Stop() + } + s.wg.Wait() + s.server = nil + if s.endpoint.path != "" { + if err := os.Remove(s.endpoint.path); err != nil && !os.IsNotExist(err) { + s.logger.Error(err, "remove Unix socket") + } + } + s.logger.V(3).Info("GRPC server stopped") +} diff --git a/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/registrationserver.go b/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/registrationserver.go new file mode 100644 index 00000000000..4f0adefb303 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/registrationserver.go @@ -0,0 +1,54 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubeletplugin + +import ( + "context" + "fmt" + + registerapi "k8s.io/kubelet/pkg/apis/pluginregistration/v1" +) + +// registrationServer implements the kubelet plugin registration gRPC interface. +type registrationServer struct { + driverName string + endpoint string + supportedVersions []string + status *registerapi.RegistrationStatus +} + +var _ registerapi.RegistrationServer = ®istrationServer{} + +// GetInfo is the RPC invoked by plugin watcher. +func (e *registrationServer) GetInfo(ctx context.Context, req *registerapi.InfoRequest) (*registerapi.PluginInfo, error) { + return ®isterapi.PluginInfo{ + Type: registerapi.DRAPlugin, + Name: e.driverName, + Endpoint: e.endpoint, + SupportedVersions: e.supportedVersions, + }, nil +} + +// NotifyRegistrationStatus is the RPC invoked by plugin watcher. +func (e *registrationServer) NotifyRegistrationStatus(ctx context.Context, status *registerapi.RegistrationStatus) (*registerapi.RegistrationStatusResponse, error) { + e.status = status + if !status.PluginRegistered { + return nil, fmt.Errorf("failed registration process: %+v", status.Error) + } + + return ®isterapi.RegistrationStatusResponse{}, nil +} diff --git a/staging/src/k8s.io/dynamic-resource-allocation/leaderelection/leaderelection.go b/staging/src/k8s.io/dynamic-resource-allocation/leaderelection/leaderelection.go new file mode 100644 index 00000000000..d6e031e4792 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/leaderelection/leaderelection.go @@ -0,0 +1,262 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package leaderelection wraps k8s.io/client-go/tools/leaderelection with a +// simpler API. It's derived from https://github.com/kubernetes-csi/csi-lib-utils/tree/v0.11.0/leaderelection +package leaderelection + +import ( + "context" + "fmt" + "net/http" + "os" + "regexp" + "strings" + "time" + + v1 "k8s.io/api/core/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/leaderelection" + "k8s.io/client-go/tools/leaderelection/resourcelock" + "k8s.io/client-go/tools/record" + "k8s.io/klog/v2" +) + +const ( + defaultLeaseDuration = 15 * time.Second + defaultRenewDeadline = 10 * time.Second + defaultRetryPeriod = 5 * time.Second + defaultHealthCheckTimeout = 20 * time.Second + + // HealthCheckerAddress is the address at which the leader election health + // checker reports status. + // The caller sidecar should document this address in appropriate flag + // descriptions. + HealthCheckerAddress = "/healthz/leader-election" +) + +// leaderElection is a convenience wrapper around client-go's leader election library. +type leaderElection struct { + runFunc func(ctx context.Context) + + // the lockName identifies the leader election config and should be shared across all members + lockName string + // the identity is the unique identity of the currently running member + identity string + // the namespace to store the lock resource + namespace string + // resourceLock defines the type of leaderelection that should be used + // Only resourcelock.LeasesResourceLock is valid at the moment. + resourceLock string + // healthCheck reports unhealthy if leader election fails to renew leadership + // within a timeout period. + healthCheck *leaderelection.HealthzAdaptor + + leaseDuration time.Duration + renewDeadline time.Duration + retryPeriod time.Duration + healthCheckTimeout time.Duration + + ctx context.Context + + clientset kubernetes.Interface +} + +// Option implements functional options for New. +type Option func(l *leaderElection) + +// New constructs a new leader election instance. +func New(clientset kubernetes.Interface, lockName string, runFunc func(ctx context.Context), opts ...Option) *leaderElection { + l := &leaderElection{ + runFunc: runFunc, + lockName: lockName, + resourceLock: resourcelock.LeasesResourceLock, + leaseDuration: defaultLeaseDuration, + renewDeadline: defaultRenewDeadline, + retryPeriod: defaultRetryPeriod, + healthCheckTimeout: defaultHealthCheckTimeout, + clientset: clientset, + } + + for _, opt := range opts { + opt(l) + } + + return l +} + +func Identity(identity string) Option { + return func(l *leaderElection) { + l.identity = identity + } +} + +func Namespace(namespace string) Option { + return func(l *leaderElection) { + l.namespace = namespace + } +} + +func LeaseDuration(leaseDuration time.Duration) Option { + return func(l *leaderElection) { + l.leaseDuration = leaseDuration + } +} + +func RenewDeadline(renewDeadline time.Duration) Option { + return func(l *leaderElection) { + l.renewDeadline = renewDeadline + } +} + +func RetryPeriod(retryPeriod time.Duration) Option { + return func(l *leaderElection) { + l.retryPeriod = retryPeriod + } +} + +func HealthCheckTimeout(timeout time.Duration) Option { + return func(l *leaderElection) { + l.healthCheckTimeout = timeout + } +} + +func Context(ctx context.Context) Option { + return func(l *leaderElection) { + l.ctx = ctx + } +} + +// Server represents any type that could serve HTTP requests for the leader +// election health check endpoint. +type Server interface { + Handle(pattern string, handler http.Handler) +} + +// PrepareHealthCheck creates a health check for this leader election object +// with the given healthCheckTimeout and registers its HTTP handler to the given +// server at the path specified by the constant "healthCheckerAddress". +// healthCheckTimeout determines the max duration beyond lease expiration +// allowed before reporting unhealthy. +// The caller sidecar should document the handler address in appropriate flag +// descriptions. +func (l *leaderElection) PrepareHealthCheck(s Server) { + l.healthCheck = leaderelection.NewLeaderHealthzAdaptor(l.healthCheckTimeout) + s.Handle(HealthCheckerAddress, adaptCheckToHandler(l.healthCheck.Check)) +} + +func (l *leaderElection) Run() error { + if l.identity == "" { + id, err := defaultLeaderElectionIdentity() + if err != nil { + return fmt.Errorf("error getting the default leader identity: %v", err) + } + + l.identity = id + } + + if l.namespace == "" { + l.namespace = inClusterNamespace() + } + + broadcaster := record.NewBroadcaster() + broadcaster.StartRecordingToSink(&corev1.EventSinkImpl{Interface: l.clientset.CoreV1().Events(l.namespace)}) + eventRecorder := broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: fmt.Sprintf("%s/%s", l.lockName, l.identity)}) + + rlConfig := resourcelock.ResourceLockConfig{ + Identity: sanitizeName(l.identity), + EventRecorder: eventRecorder, + } + + lock, err := resourcelock.New(l.resourceLock, l.namespace, sanitizeName(l.lockName), l.clientset.CoreV1(), l.clientset.CoordinationV1(), rlConfig) + if err != nil { + return err + } + + ctx := l.ctx + if ctx == nil { + ctx = context.Background() + } + leaderConfig := leaderelection.LeaderElectionConfig{ + Lock: lock, + LeaseDuration: l.leaseDuration, + RenewDeadline: l.renewDeadline, + RetryPeriod: l.retryPeriod, + Callbacks: leaderelection.LeaderCallbacks{ + OnStartedLeading: func(ctx context.Context) { + klog.FromContext(ctx).Info("became leader, starting") + l.runFunc(ctx) + }, + OnStoppedLeading: func() { + klog.FromContext(ctx).Error(nil, "stopped leading") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + }, + OnNewLeader: func(identity string) { + klog.FromContext(ctx).Info("new leader detected", "idendity", identity) + }, + }, + WatchDog: l.healthCheck, + } + + leaderelection.RunOrDie(ctx, leaderConfig) + return nil // should never reach here +} + +func defaultLeaderElectionIdentity() (string, error) { + return os.Hostname() +} + +// sanitizeName sanitizes the provided string so it can be consumed by leader election library +func sanitizeName(name string) string { + re := regexp.MustCompile("[^a-zA-Z0-9-]") + name = re.ReplaceAllString(name, "-") + if name[len(name)-1] == '-' { + // name must not end with '-' + name = name + "X" + } + return name +} + +// inClusterNamespace returns the namespace in which the pod is running in by checking +// the env var POD_NAMESPACE, then the file /var/run/secrets/kubernetes.io/serviceaccount/namespace. +// if neither returns a valid namespace, the "default" namespace is returned +func inClusterNamespace() string { + if ns := os.Getenv("POD_NAMESPACE"); ns != "" { + return ns + } + + if data, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil { + if ns := strings.TrimSpace(string(data)); len(ns) > 0 { + return ns + } + } + + return "default" +} + +// adaptCheckToHandler returns an http.HandlerFunc that serves the provided checks. +func adaptCheckToHandler(c func(r *http.Request) error) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + err := c(r) + if err != nil { + http.Error(w, fmt.Sprintf("internal server error: %v", err), http.StatusInternalServerError) + } else { + fmt.Fprint(w, "ok") + } + }) +} diff --git a/staging/src/k8s.io/dynamic-resource-allocation/resourceclaim/resourceclaim.go b/staging/src/k8s.io/dynamic-resource-allocation/resourceclaim/resourceclaim.go new file mode 100644 index 00000000000..5d5eb94c5e8 --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/resourceclaim/resourceclaim.go @@ -0,0 +1,81 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package resourceclaim provides code that supports the usual pattern +// for accessing the ResourceClaim that is referenced by a PodResourceClaim: +// +// - determine the ResourceClaim name that corresponds to the PodResourceClaim +// - retrieve the ResourceClaim +// - verify that the ResourceClaim is owned by the pod if generated from a template +// - use the ResourceClaim +package resourceclaim + +import ( + "fmt" + + v1 "k8s.io/api/core/v1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// Name returns the name of the ResourceClaim object that gets referenced by or +// created for the PodResourceClaim. The name is deterministic and therefore +// this function does not need any additional information and it will never +// fail. +// +// Either podClaim.ResourceClaimName or podClaim.Template must be non-nil, but not +// both. This is enforced by API validation. +// +// If podClaim.Template is not nil, the caller must check that the +// ResourceClaim is indeed the one that was created for the Pod by calling +// IsUsable. +func Name(pod *v1.Pod, podClaim *v1.PodResourceClaim) string { + if podClaim.Source.ResourceClaimName != nil { + return *podClaim.Source.ResourceClaimName + } + return pod.Name + "-" + podClaim.Name +} + +// IsForPod checks that the ResourceClaim is the ephemeral volume that +// was created for the Pod. It returns an error that is informative +// enough to be returned by the caller without adding further details +// about the Pod or ResourceClaim. +func IsForPod(pod *v1.Pod, claim *resourcev1alpha1.ResourceClaim) error { + // Checking the namespaces is just a precaution. The caller should + // never pass in a ResourceClaim that isn't from the same namespace as the + // Pod. + if claim.Namespace != pod.Namespace || !metav1.IsControlledBy(claim, pod) { + return fmt.Errorf("ResourceClaim %s/%s was not created for pod %s/%s (pod is not owner)", claim.Namespace, claim.Name, pod.Namespace, pod.Name) + } + return nil +} + +// IsReservedForPod checks whether a claim lists the pod as one of the objects +// that the claim was reserved for. +func IsReservedForPod(pod *v1.Pod, claim *resourcev1alpha1.ResourceClaim) bool { + for _, reserved := range claim.Status.ReservedFor { + if reserved.UID == pod.UID { + return true + } + } + return false +} + +// CanBeReserved checks whether the claim could be reserved for another object. +func CanBeReserved(claim *resourcev1alpha1.ResourceClaim) bool { + return claim.Status.Allocation.Shareable || + len(claim.Status.ReservedFor) == 0 +} diff --git a/staging/src/k8s.io/dynamic-resource-allocation/resourceclaim/resourceclaim_test.go b/staging/src/k8s.io/dynamic-resource-allocation/resourceclaim/resourceclaim_test.go new file mode 100644 index 00000000000..75dd49ca4df --- /dev/null +++ b/staging/src/k8s.io/dynamic-resource-allocation/resourceclaim/resourceclaim_test.go @@ -0,0 +1,127 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourceclaim + +import ( + "fmt" + "testing" + + v1 "k8s.io/api/core/v1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +func TestResourceClaimIsForPod(t *testing.T) { + uid := 0 + newUID := func() types.UID { + uid++ + return types.UID(fmt.Sprintf("%d", uid)) + } + isController := true + + podNotOwner := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "kube-system", + Name: "podNotOwner", + UID: newUID(), + }, + } + podOwner := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "kube-system", + Name: "podOwner", + UID: newUID(), + }, + } + claimNoOwner := &resourcev1alpha1.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "kube-system", + Name: "claimNoOwner", + UID: newUID(), + }, + } + claimWithOwner := &resourcev1alpha1.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "kube-system", + Name: "claimNoOwner", + UID: newUID(), + OwnerReferences: []metav1.OwnerReference{ + { + UID: podOwner.UID, + Controller: &isController, + }, + }, + }, + } + userClaimWithOwner := &resourcev1alpha1.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "user-namespace", + Name: "userClaimWithOwner", + UID: newUID(), + OwnerReferences: []metav1.OwnerReference{ + { + UID: podOwner.UID, + Controller: &isController, + }, + }, + }, + } + + testcases := map[string]struct { + pod *v1.Pod + claim *resourcev1alpha1.ResourceClaim + expectedError string + }{ + "owned": { + pod: podOwner, + claim: claimWithOwner, + }, + "other-pod": { + pod: podNotOwner, + claim: claimWithOwner, + expectedError: `ResourceClaim kube-system/claimNoOwner was not created for pod kube-system/podNotOwner (pod is not owner)`, + }, + "no-owner": { + pod: podOwner, + claim: claimNoOwner, + expectedError: `ResourceClaim kube-system/claimNoOwner was not created for pod kube-system/podOwner (pod is not owner)`, + }, + "different-namespace": { + pod: podOwner, + claim: userClaimWithOwner, + expectedError: `ResourceClaim user-namespace/userClaimWithOwner was not created for pod kube-system/podOwner (pod is not owner)`, + }, + } + + for name, tc := range testcases { + t.Run(name, func(t *testing.T) { + err := IsForPod(tc.pod, tc.claim) + if tc.expectedError == "" { + if err != nil { + t.Errorf("expected no error, got %v", err) + } + } else { + if err == nil { + t.Errorf("expected error %q, got nil", tc.expectedError) + } else if tc.expectedError != err.Error() { + t.Errorf("expected error %q, got %v", tc.expectedError, err) + } + } + }) + } +} diff --git a/staging/src/k8s.io/kubelet/pkg/apis/dra/OWNERS b/staging/src/k8s.io/kubelet/pkg/apis/dra/OWNERS new file mode 100644 index 00000000000..03cc9aff5b4 --- /dev/null +++ b/staging/src/k8s.io/kubelet/pkg/apis/dra/OWNERS @@ -0,0 +1,11 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - klueska + - pohly +reviewers: + - klueska + - pohly + - bart0sh +labels: + - sig/node diff --git a/staging/src/k8s.io/kubelet/pkg/apis/dra/v1alpha1/api.pb.go b/staging/src/k8s.io/kubelet/pkg/apis/dra/v1alpha1/api.pb.go new file mode 100644 index 00000000000..bd50df30554 --- /dev/null +++ b/staging/src/k8s.io/kubelet/pkg/apis/dra/v1alpha1/api.pb.go @@ -0,0 +1,1314 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: api.proto + +package dra + +import ( + context "context" + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" + reflect "reflect" + strings "strings" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type NodePrepareResourceRequest struct { + // The ResourceClaim namespace (ResourceClaim.meta.Namespace). + // This field is REQUIRED. + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + // The UID of the Resource claim (ResourceClaim.meta.UUID). + // This field is REQUIRED. + ClaimUid string `protobuf:"bytes,2,opt,name=claim_uid,json=claimUid,proto3" json:"claim_uid,omitempty"` + // The name of the Resource claim (ResourceClaim.meta.Name) + // This field is REQUIRED. + ClaimName string `protobuf:"bytes,3,opt,name=claim_name,json=claimName,proto3" json:"claim_name,omitempty"` + // Resource handle (AllocationResult.ResourceHandle) + // This field is REQUIRED. + ResourceHandle string `protobuf:"bytes,4,opt,name=resource_handle,json=resourceHandle,proto3" json:"resource_handle,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NodePrepareResourceRequest) Reset() { *m = NodePrepareResourceRequest{} } +func (*NodePrepareResourceRequest) ProtoMessage() {} +func (*NodePrepareResourceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{0} +} +func (m *NodePrepareResourceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NodePrepareResourceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NodePrepareResourceRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NodePrepareResourceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodePrepareResourceRequest.Merge(m, src) +} +func (m *NodePrepareResourceRequest) XXX_Size() int { + return m.Size() +} +func (m *NodePrepareResourceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_NodePrepareResourceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_NodePrepareResourceRequest proto.InternalMessageInfo + +func (m *NodePrepareResourceRequest) GetNamespace() string { + if m != nil { + return m.Namespace + } + return "" +} + +func (m *NodePrepareResourceRequest) GetClaimUid() string { + if m != nil { + return m.ClaimUid + } + return "" +} + +func (m *NodePrepareResourceRequest) GetClaimName() string { + if m != nil { + return m.ClaimName + } + return "" +} + +func (m *NodePrepareResourceRequest) GetResourceHandle() string { + if m != nil { + return m.ResourceHandle + } + return "" +} + +type NodePrepareResourceResponse struct { + // These are the additional devices that kubelet must + // make available via the container runtime. A resource + // may have zero or more devices. + CdiDevices []string `protobuf:"bytes,1,rep,name=cdi_devices,json=cdiDevices,proto3" json:"cdi_devices,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NodePrepareResourceResponse) Reset() { *m = NodePrepareResourceResponse{} } +func (*NodePrepareResourceResponse) ProtoMessage() {} +func (*NodePrepareResourceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{1} +} +func (m *NodePrepareResourceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NodePrepareResourceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NodePrepareResourceResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NodePrepareResourceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodePrepareResourceResponse.Merge(m, src) +} +func (m *NodePrepareResourceResponse) XXX_Size() int { + return m.Size() +} +func (m *NodePrepareResourceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_NodePrepareResourceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_NodePrepareResourceResponse proto.InternalMessageInfo + +func (m *NodePrepareResourceResponse) GetCdiDevices() []string { + if m != nil { + return m.CdiDevices + } + return nil +} + +type NodeUnprepareResourceRequest struct { + // The ResourceClaim namespace (ResourceClaim.meta.Namespace). + // This field is REQUIRED. + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + // The UID of the Resource claim (ResourceClaim.meta.UUID). + // This field is REQUIRED. + ClaimUid string `protobuf:"bytes,2,opt,name=claim_uid,json=claimUid,proto3" json:"claim_uid,omitempty"` + // The name of the Resource claim (ResourceClaim.meta.Name) + // This field is REQUIRED. + ClaimName string `protobuf:"bytes,3,opt,name=claim_name,json=claimName,proto3" json:"claim_name,omitempty"` + // List of fully qualified CDI device names + // Kubelet plugin returns them in the NodePrepareResourceResponse + CdiDevices []string `protobuf:"bytes,4,rep,name=cdi_devices,json=cdiDevices,proto3" json:"cdi_devices,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NodeUnprepareResourceRequest) Reset() { *m = NodeUnprepareResourceRequest{} } +func (*NodeUnprepareResourceRequest) ProtoMessage() {} +func (*NodeUnprepareResourceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{2} +} +func (m *NodeUnprepareResourceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NodeUnprepareResourceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NodeUnprepareResourceRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NodeUnprepareResourceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeUnprepareResourceRequest.Merge(m, src) +} +func (m *NodeUnprepareResourceRequest) XXX_Size() int { + return m.Size() +} +func (m *NodeUnprepareResourceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_NodeUnprepareResourceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeUnprepareResourceRequest proto.InternalMessageInfo + +func (m *NodeUnprepareResourceRequest) GetNamespace() string { + if m != nil { + return m.Namespace + } + return "" +} + +func (m *NodeUnprepareResourceRequest) GetClaimUid() string { + if m != nil { + return m.ClaimUid + } + return "" +} + +func (m *NodeUnprepareResourceRequest) GetClaimName() string { + if m != nil { + return m.ClaimName + } + return "" +} + +func (m *NodeUnprepareResourceRequest) GetCdiDevices() []string { + if m != nil { + return m.CdiDevices + } + return nil +} + +type NodeUnprepareResourceResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NodeUnprepareResourceResponse) Reset() { *m = NodeUnprepareResourceResponse{} } +func (*NodeUnprepareResourceResponse) ProtoMessage() {} +func (*NodeUnprepareResourceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{3} +} +func (m *NodeUnprepareResourceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NodeUnprepareResourceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NodeUnprepareResourceResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NodeUnprepareResourceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_NodeUnprepareResourceResponse.Merge(m, src) +} +func (m *NodeUnprepareResourceResponse) XXX_Size() int { + return m.Size() +} +func (m *NodeUnprepareResourceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_NodeUnprepareResourceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_NodeUnprepareResourceResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*NodePrepareResourceRequest)(nil), "v1alpha1.NodePrepareResourceRequest") + proto.RegisterType((*NodePrepareResourceResponse)(nil), "v1alpha1.NodePrepareResourceResponse") + proto.RegisterType((*NodeUnprepareResourceRequest)(nil), "v1alpha1.NodeUnprepareResourceRequest") + proto.RegisterType((*NodeUnprepareResourceResponse)(nil), "v1alpha1.NodeUnprepareResourceResponse") +} + +func init() { proto.RegisterFile("api.proto", fileDescriptor_00212fb1f9d3bf1c) } + +var fileDescriptor_00212fb1f9d3bf1c = []byte{ + // 348 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x52, 0x31, 0x4f, 0x32, 0x41, + 0x10, 0x65, 0x3f, 0xc8, 0x17, 0x6e, 0x4c, 0x34, 0x59, 0x63, 0x72, 0x39, 0xe0, 0xc0, 0x8b, 0x0a, + 0x8d, 0x47, 0xd0, 0xde, 0xc2, 0x58, 0x58, 0x11, 0x73, 0x09, 0x8d, 0x0d, 0x59, 0x76, 0x47, 0x58, + 0xc3, 0xdd, 0xae, 0x77, 0x1c, 0xb5, 0x3f, 0xc1, 0xd6, 0xca, 0xbf, 0x43, 0x69, 0x49, 0x29, 0xe7, + 0x1f, 0x31, 0xec, 0x49, 0x8c, 0x0a, 0xa1, 0xb3, 0xdb, 0x79, 0xf3, 0x66, 0xde, 0x9b, 0x99, 0x05, + 0x8b, 0x69, 0xe9, 0xeb, 0x58, 0x4d, 0x14, 0x2d, 0x4f, 0x3b, 0x6c, 0xac, 0x47, 0xac, 0xe3, 0x9c, + 0x0e, 0xe5, 0x64, 0x94, 0x0e, 0x7c, 0xae, 0xc2, 0xf6, 0x50, 0x0d, 0x55, 0xdb, 0x10, 0x06, 0xe9, + 0x9d, 0x89, 0x4c, 0x60, 0x5e, 0x79, 0xa1, 0xf7, 0x42, 0xc0, 0xe9, 0x2a, 0x81, 0x37, 0x31, 0x6a, + 0x16, 0x63, 0x80, 0x89, 0x4a, 0x63, 0x8e, 0x01, 0x3e, 0xa4, 0x98, 0x4c, 0x68, 0x15, 0xac, 0x88, + 0x85, 0x98, 0x68, 0xc6, 0xd1, 0x26, 0x0d, 0xd2, 0xb2, 0x82, 0x2f, 0x80, 0x56, 0xc0, 0xe2, 0x63, + 0x26, 0xc3, 0x7e, 0x2a, 0x85, 0xfd, 0xcf, 0x64, 0xcb, 0x06, 0xe8, 0x49, 0x41, 0x6b, 0x00, 0x79, + 0x72, 0xc9, 0xb7, 0x8b, 0x79, 0xad, 0x41, 0xba, 0x2c, 0x44, 0xda, 0x84, 0xbd, 0xf8, 0x53, 0xac, + 0x3f, 0x62, 0x91, 0x18, 0xa3, 0x5d, 0x32, 0x9c, 0xdd, 0x15, 0x7c, 0x6d, 0x50, 0xef, 0x02, 0x2a, + 0x6b, 0x0d, 0x26, 0x5a, 0x45, 0x09, 0xd2, 0x3a, 0xec, 0x70, 0x21, 0xfb, 0x02, 0xa7, 0x92, 0x63, + 0x62, 0x93, 0x46, 0xb1, 0x65, 0x05, 0xc0, 0x85, 0xbc, 0xca, 0x11, 0xef, 0x99, 0x40, 0x75, 0xd9, + 0xa0, 0x17, 0xe9, 0xbf, 0x9e, 0xf1, 0x87, 0xb7, 0xd2, 0x2f, 0x6f, 0x75, 0xa8, 0x6d, 0xb0, 0x96, + 0x4f, 0x77, 0x36, 0x27, 0x50, 0x5a, 0x32, 0xa8, 0x80, 0xfd, 0x35, 0x5b, 0xa0, 0x47, 0xfe, 0xea, + 0xf0, 0xfe, 0xe6, 0x2b, 0x3a, 0xc7, 0x5b, 0x58, 0xb9, 0x98, 0x57, 0xa0, 0xf7, 0x70, 0xb0, 0xd6, + 0x0f, 0x3d, 0xf9, 0xde, 0x61, 0xd3, 0x2e, 0x9d, 0xe6, 0x56, 0xde, 0x4a, 0xeb, 0xf2, 0x70, 0xb6, + 0x70, 0xc9, 0x7c, 0xe1, 0x16, 0x1e, 0x33, 0x97, 0xcc, 0x32, 0x97, 0xbc, 0x66, 0x2e, 0x79, 0xcb, + 0x5c, 0xf2, 0xf4, 0xee, 0x16, 0x6e, 0x8b, 0x22, 0x66, 0x83, 0xff, 0xe6, 0x8f, 0x9e, 0x7f, 0x04, + 0x00, 0x00, 0xff, 0xff, 0xab, 0xb6, 0x01, 0xe3, 0xe9, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// NodeClient is the client API for Node service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type NodeClient interface { + NodePrepareResource(ctx context.Context, in *NodePrepareResourceRequest, opts ...grpc.CallOption) (*NodePrepareResourceResponse, error) + NodeUnprepareResource(ctx context.Context, in *NodeUnprepareResourceRequest, opts ...grpc.CallOption) (*NodeUnprepareResourceResponse, error) +} + +type nodeClient struct { + cc *grpc.ClientConn +} + +func NewNodeClient(cc *grpc.ClientConn) NodeClient { + return &nodeClient{cc} +} + +func (c *nodeClient) NodePrepareResource(ctx context.Context, in *NodePrepareResourceRequest, opts ...grpc.CallOption) (*NodePrepareResourceResponse, error) { + out := new(NodePrepareResourceResponse) + err := c.cc.Invoke(ctx, "/v1alpha1.Node/NodePrepareResource", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nodeClient) NodeUnprepareResource(ctx context.Context, in *NodeUnprepareResourceRequest, opts ...grpc.CallOption) (*NodeUnprepareResourceResponse, error) { + out := new(NodeUnprepareResourceResponse) + err := c.cc.Invoke(ctx, "/v1alpha1.Node/NodeUnprepareResource", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// NodeServer is the server API for Node service. +type NodeServer interface { + NodePrepareResource(context.Context, *NodePrepareResourceRequest) (*NodePrepareResourceResponse, error) + NodeUnprepareResource(context.Context, *NodeUnprepareResourceRequest) (*NodeUnprepareResourceResponse, error) +} + +// UnimplementedNodeServer can be embedded to have forward compatible implementations. +type UnimplementedNodeServer struct { +} + +func (*UnimplementedNodeServer) NodePrepareResource(ctx context.Context, req *NodePrepareResourceRequest) (*NodePrepareResourceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method NodePrepareResource not implemented") +} +func (*UnimplementedNodeServer) NodeUnprepareResource(ctx context.Context, req *NodeUnprepareResourceRequest) (*NodeUnprepareResourceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method NodeUnprepareResource not implemented") +} + +func RegisterNodeServer(s *grpc.Server, srv NodeServer) { + s.RegisterService(&_Node_serviceDesc, srv) +} + +func _Node_NodePrepareResource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NodePrepareResourceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServer).NodePrepareResource(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/v1alpha1.Node/NodePrepareResource", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServer).NodePrepareResource(ctx, req.(*NodePrepareResourceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Node_NodeUnprepareResource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NodeUnprepareResourceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServer).NodeUnprepareResource(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/v1alpha1.Node/NodeUnprepareResource", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServer).NodeUnprepareResource(ctx, req.(*NodeUnprepareResourceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Node_serviceDesc = grpc.ServiceDesc{ + ServiceName: "v1alpha1.Node", + HandlerType: (*NodeServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "NodePrepareResource", + Handler: _Node_NodePrepareResource_Handler, + }, + { + MethodName: "NodeUnprepareResource", + Handler: _Node_NodeUnprepareResource_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "api.proto", +} + +func (m *NodePrepareResourceRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NodePrepareResourceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NodePrepareResourceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ResourceHandle) > 0 { + i -= len(m.ResourceHandle) + copy(dAtA[i:], m.ResourceHandle) + i = encodeVarintApi(dAtA, i, uint64(len(m.ResourceHandle))) + i-- + dAtA[i] = 0x22 + } + if len(m.ClaimName) > 0 { + i -= len(m.ClaimName) + copy(dAtA[i:], m.ClaimName) + i = encodeVarintApi(dAtA, i, uint64(len(m.ClaimName))) + i-- + dAtA[i] = 0x1a + } + if len(m.ClaimUid) > 0 { + i -= len(m.ClaimUid) + copy(dAtA[i:], m.ClaimUid) + i = encodeVarintApi(dAtA, i, uint64(len(m.ClaimUid))) + i-- + dAtA[i] = 0x12 + } + if len(m.Namespace) > 0 { + i -= len(m.Namespace) + copy(dAtA[i:], m.Namespace) + i = encodeVarintApi(dAtA, i, uint64(len(m.Namespace))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *NodePrepareResourceResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NodePrepareResourceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NodePrepareResourceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.CdiDevices) > 0 { + for iNdEx := len(m.CdiDevices) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.CdiDevices[iNdEx]) + copy(dAtA[i:], m.CdiDevices[iNdEx]) + i = encodeVarintApi(dAtA, i, uint64(len(m.CdiDevices[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *NodeUnprepareResourceRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NodeUnprepareResourceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NodeUnprepareResourceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.CdiDevices) > 0 { + for iNdEx := len(m.CdiDevices) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.CdiDevices[iNdEx]) + copy(dAtA[i:], m.CdiDevices[iNdEx]) + i = encodeVarintApi(dAtA, i, uint64(len(m.CdiDevices[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if len(m.ClaimName) > 0 { + i -= len(m.ClaimName) + copy(dAtA[i:], m.ClaimName) + i = encodeVarintApi(dAtA, i, uint64(len(m.ClaimName))) + i-- + dAtA[i] = 0x1a + } + if len(m.ClaimUid) > 0 { + i -= len(m.ClaimUid) + copy(dAtA[i:], m.ClaimUid) + i = encodeVarintApi(dAtA, i, uint64(len(m.ClaimUid))) + i-- + dAtA[i] = 0x12 + } + if len(m.Namespace) > 0 { + i -= len(m.Namespace) + copy(dAtA[i:], m.Namespace) + i = encodeVarintApi(dAtA, i, uint64(len(m.Namespace))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *NodeUnprepareResourceResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NodeUnprepareResourceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NodeUnprepareResourceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintApi(dAtA []byte, offset int, v uint64) int { + offset -= sovApi(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *NodePrepareResourceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Namespace) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.ClaimUid) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.ClaimName) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.ResourceHandle) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *NodePrepareResourceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.CdiDevices) > 0 { + for _, s := range m.CdiDevices { + l = len(s) + n += 1 + l + sovApi(uint64(l)) + } + } + return n +} + +func (m *NodeUnprepareResourceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Namespace) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.ClaimUid) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + l = len(m.ClaimName) + if l > 0 { + n += 1 + l + sovApi(uint64(l)) + } + if len(m.CdiDevices) > 0 { + for _, s := range m.CdiDevices { + l = len(s) + n += 1 + l + sovApi(uint64(l)) + } + } + return n +} + +func (m *NodeUnprepareResourceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovApi(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozApi(x uint64) (n int) { + return sovApi(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *NodePrepareResourceRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&NodePrepareResourceRequest{`, + `Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`, + `ClaimUid:` + fmt.Sprintf("%v", this.ClaimUid) + `,`, + `ClaimName:` + fmt.Sprintf("%v", this.ClaimName) + `,`, + `ResourceHandle:` + fmt.Sprintf("%v", this.ResourceHandle) + `,`, + `}`, + }, "") + return s +} +func (this *NodePrepareResourceResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&NodePrepareResourceResponse{`, + `CdiDevices:` + fmt.Sprintf("%v", this.CdiDevices) + `,`, + `}`, + }, "") + return s +} +func (this *NodeUnprepareResourceRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&NodeUnprepareResourceRequest{`, + `Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`, + `ClaimUid:` + fmt.Sprintf("%v", this.ClaimUid) + `,`, + `ClaimName:` + fmt.Sprintf("%v", this.ClaimName) + `,`, + `CdiDevices:` + fmt.Sprintf("%v", this.CdiDevices) + `,`, + `}`, + }, "") + return s +} +func (this *NodeUnprepareResourceResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&NodeUnprepareResourceResponse{`, + `}`, + }, "") + return s +} +func valueToStringApi(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *NodePrepareResourceRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NodePrepareResourceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NodePrepareResourceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Namespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClaimUid", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClaimUid = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClaimName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClaimName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResourceHandle", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ResourceHandle = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NodePrepareResourceResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NodePrepareResourceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NodePrepareResourceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CdiDevices", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CdiDevices = append(m.CdiDevices, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NodeUnprepareResourceRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NodeUnprepareResourceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NodeUnprepareResourceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Namespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClaimUid", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClaimUid = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClaimName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClaimName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CdiDevices", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CdiDevices = append(m.CdiDevices, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NodeUnprepareResourceResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NodeUnprepareResourceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NodeUnprepareResourceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipApi(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowApi + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthApi + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupApi + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthApi + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthApi = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowApi = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupApi = fmt.Errorf("proto: unexpected end of group") +) diff --git a/staging/src/k8s.io/kubelet/pkg/apis/dra/v1alpha1/api.proto b/staging/src/k8s.io/kubelet/pkg/apis/dra/v1alpha1/api.proto new file mode 100644 index 00000000000..2ba5c5c34d4 --- /dev/null +++ b/staging/src/k8s.io/kubelet/pkg/apis/dra/v1alpha1/api.proto @@ -0,0 +1,81 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// To regenerate api.pb.go run hack/update-generated-kubelet-plugin-registration.sh + +syntax = "proto3"; + +package v1alpha1; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +option go_package = "dra"; +option (gogoproto.goproto_stringer_all) = false; +option (gogoproto.stringer_all) = true; +option (gogoproto.goproto_getters_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.goproto_unrecognized_all) = false; + +service Node { + rpc NodePrepareResource (NodePrepareResourceRequest) + returns (NodePrepareResourceResponse) {} + + rpc NodeUnprepareResource (NodeUnprepareResourceRequest) + returns (NodeUnprepareResourceResponse) {} +} + +message NodePrepareResourceRequest { + // The ResourceClaim namespace (ResourceClaim.meta.Namespace). + // This field is REQUIRED. + string namespace = 1; + // The UID of the Resource claim (ResourceClaim.meta.UUID). + // This field is REQUIRED. + string claim_uid = 2; + // The name of the Resource claim (ResourceClaim.meta.Name) + // This field is REQUIRED. + string claim_name = 3; + // Resource handle (AllocationResult.ResourceHandle) + // This field is REQUIRED. + string resource_handle = 4; +} + +message NodePrepareResourceResponse { + // These are the additional devices that kubelet must + // make available via the container runtime. A resource + // may have zero or more devices. + repeated string cdi_devices = 1; +} + +message NodeUnprepareResourceRequest { + // The ResourceClaim namespace (ResourceClaim.meta.Namespace). + // This field is REQUIRED. + string namespace = 1; + // The UID of the Resource claim (ResourceClaim.meta.UUID). + // This field is REQUIRED. + string claim_uid = 2; + // The name of the Resource claim (ResourceClaim.meta.Name) + // This field is REQUIRED. + string claim_name = 3; + // List of fully qualified CDI device names + // Kubelet plugin returns them in the NodePrepareResourceResponse + repeated string cdi_devices = 4; +} + +message NodeUnprepareResourceResponse { + // Intentionally empty. +} \ No newline at end of file diff --git a/staging/src/k8s.io/kubelet/pkg/apis/pluginregistration/v1/constants.go b/staging/src/k8s.io/kubelet/pkg/apis/pluginregistration/v1/constants.go index 7708f758fa2..5efe743d368 100644 --- a/staging/src/k8s.io/kubelet/pkg/apis/pluginregistration/v1/constants.go +++ b/staging/src/k8s.io/kubelet/pkg/apis/pluginregistration/v1/constants.go @@ -21,4 +21,6 @@ const ( CSIPlugin = "CSIPlugin" // DevicePlugin identifier for registered device plugins DevicePlugin = "DevicePlugin" + // DRAPlugin identifier for registered Dynamic Resourc Allocation plugins + DRAPlugin = "DRAPlugin" ) diff --git a/test/e2e/dra/OWNERS b/test/e2e/dra/OWNERS new file mode 100644 index 00000000000..03cc9aff5b4 --- /dev/null +++ b/test/e2e/dra/OWNERS @@ -0,0 +1,11 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - klueska + - pohly +reviewers: + - klueska + - pohly + - bart0sh +labels: + - sig/node diff --git a/test/e2e/dra/README.md b/test/e2e/dra/README.md new file mode 100644 index 00000000000..b390a477879 --- /dev/null +++ b/test/e2e/dra/README.md @@ -0,0 +1,23 @@ +# Overview + +The tests in this directory cover dynamic resource allocation support in +Kubernetes. They do not test the correct behavior of arbitrary dynamic resource +allocation drivers. + +If such a driver is needed, then the in-tree test/e2e/dra/test-driver is used, +with a slight twist: instead of deploying that driver directly in the cluster, +the necessary sockets for interaction with kubelet (registration and dynamic +resource allocation) get proxied into the e2e.test binary. This reuses the work +done for CSI mock testing. The advantage is that no separate images are needed +for the test driver and that the e2e test has full control over all gRPC calls, +in case that it needs that for operations like error injection or checking +calls. + +# Cluster setup + +The container runtime must support CDI. The latest cri-o releases contain +support, containerd 1.6.x does not. To bring up a kind cluster with containerd +built from their main branch, use: + + test/e2e/dra/kind-build-image.sh dra/node:latest && \ + kind create cluster --config test/e2e/dra/kind.yaml --image dra/node:latest diff --git a/test/e2e/dra/deploy.go b/test/e2e/dra/deploy.go new file mode 100644 index 00000000000..7a6bc35f9d0 --- /dev/null +++ b/test/e2e/dra/deploy.go @@ -0,0 +1,339 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dra + +import ( + "bytes" + "context" + "errors" + "fmt" + "net" + "path" + "sort" + "sync" + "time" + + "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" + "google.golang.org/grpc" + + appsv1 "k8s.io/api/apps/v1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + "k8s.io/dynamic-resource-allocation/kubeletplugin" + "k8s.io/klog/v2" + "k8s.io/kubernetes/test/e2e/dra/test-driver/app" + "k8s.io/kubernetes/test/e2e/framework" + e2enode "k8s.io/kubernetes/test/e2e/framework/node" + e2ereplicaset "k8s.io/kubernetes/test/e2e/framework/replicaset" + e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" + "k8s.io/kubernetes/test/e2e/storage/drivers/proxy" + "k8s.io/kubernetes/test/e2e/storage/utils" +) + +const ( + NodePrepareResourceMethod = "/v1alpha1.Node/NodePrepareResource" + NodeUnprepareResourceMethod = "/v1alpha1.Node/NodeUnprepareResource" +) + +type Nodes struct { + NodeNames []string +} + +// NewNodes selects nodes to run the test on. +func NewNodes(f *framework.Framework, minNodes, maxNodes int) *Nodes { + nodes := &Nodes{} + ginkgo.BeforeEach(func() { + ginkgo.By("selecting nodes") + // The kubelet plugin is harder. We deploy the builtin manifest + // after patching in the driver name and all nodes on which we + // want the plugin to run. + // + // Only a subset of the nodes are picked to avoid causing + // unnecessary load on a big cluster. + nodeList, err := e2enode.GetBoundedReadySchedulableNodes(f.ClientSet, maxNodes) + framework.ExpectNoError(err, "get nodes") + numNodes := int32(len(nodeList.Items)) + if int(numNodes) < minNodes { + e2eskipper.Skipf("%d ready nodes required, only have %d", minNodes, numNodes) + } + nodes.NodeNames = nil + for _, node := range nodeList.Items { + nodes.NodeNames = append(nodes.NodeNames, node.Name) + } + framework.Logf("testing on nodes %v", nodes.NodeNames) + }) + return nodes +} + +// NewDriver sets up controller (as client of the cluster) and +// kubelet plugin (via proxy) before the test runs. It cleans +// up after the test. +func NewDriver(f *framework.Framework, nodes *Nodes, configureResources func() app.Resources) *Driver { + d := &Driver{ + f: f, + fail: map[MethodInstance]bool{}, + callCounts: map[MethodInstance]int64{}, + } + + ginkgo.BeforeEach(func() { + resources := configureResources() + if len(resources.Nodes) == 0 { + // This always has to be set because the driver might + // not run on all nodes. + resources.Nodes = nodes.NodeNames + } + d.SetUp(nodes, resources) + ginkgo.DeferCleanup(d.TearDown) + }) + return d +} + +type MethodInstance struct { + Nodename string + FullMethod string +} + +type Driver struct { + f *framework.Framework + ctx context.Context + cleanup []func() // executed first-in-first-out + wg sync.WaitGroup + + NameSuffix string + Controller *app.ExampleController + Name string + Nodes map[string]*app.ExamplePlugin + + mutex sync.Mutex + fail map[MethodInstance]bool + callCounts map[MethodInstance]int64 +} + +func (d *Driver) SetUp(nodes *Nodes, resources app.Resources) { + ginkgo.By(fmt.Sprintf("deploying driver on nodes %v", nodes.NodeNames)) + d.Nodes = map[string]*app.ExamplePlugin{} + d.Name = d.f.UniqueName + d.NameSuffix + ".k8s.io" + + ctx, cancel := context.WithCancel(context.Background()) + if d.NameSuffix != "" { + logger := klog.FromContext(ctx) + logger = klog.LoggerWithName(logger, "instance"+d.NameSuffix) + ctx = klog.NewContext(ctx, logger) + } + d.ctx = ctx + d.cleanup = append(d.cleanup, cancel) + + // The controller is easy: we simply connect to the API server. It + // would be slightly nicer if we had a way to wait for all goroutines, but + // SharedInformerFactory has no API for that. At least we can wait + // for our own goroutine to stop once the context gets cancelled. + d.Controller = app.NewController(d.f.ClientSet, d.Name, resources) + d.wg.Add(1) + go func() { + defer d.wg.Done() + d.Controller.Run(d.ctx, 5 /* workers */) + }() + + manifests := []string{ + // The code below matches the content of this manifest (ports, + // container names, etc.). + "test/e2e/testing-manifests/dra/dra-test-driver-proxy.yaml", + } + instanceKey := "app.kubernetes.io/instance" + rsName := "" + draAddr := path.Join(framework.TestContext.KubeletRootDir, "plugins", d.Name+".sock") + numNodes := int32(len(nodes.NodeNames)) + undeploy, err := utils.CreateFromManifests(d.f, d.f.Namespace, func(item interface{}) error { + switch item := item.(type) { + case *appsv1.ReplicaSet: + item.Name += d.NameSuffix + rsName = item.Name + item.Spec.Replicas = &numNodes + item.Spec.Selector.MatchLabels[instanceKey] = d.Name + item.Spec.Template.Labels[instanceKey] = d.Name + item.Spec.Template.Spec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution[0].LabelSelector.MatchLabels[instanceKey] = d.Name + item.Spec.Template.Spec.Affinity.NodeAffinity = &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "kubernetes.io/hostname", + Operator: v1.NodeSelectorOpIn, + Values: nodes.NodeNames, + }, + }, + }, + }, + }, + } + item.Spec.Template.Spec.Volumes[0].HostPath.Path = path.Join(framework.TestContext.KubeletRootDir, "plugins") + item.Spec.Template.Spec.Volumes[2].HostPath.Path = path.Join(framework.TestContext.KubeletRootDir, "plugins_registry") + item.Spec.Template.Spec.Containers[0].Args = append(item.Spec.Template.Spec.Containers[0].Args, "--endpoint=/plugins_registry/"+d.Name+"-reg.sock") + item.Spec.Template.Spec.Containers[1].Args = append(item.Spec.Template.Spec.Containers[1].Args, "--endpoint=/dra/"+d.Name+".sock") + } + return nil + }, manifests...) + framework.ExpectNoError(err, "deploy kubelet plugin replicaset") + d.cleanup = append(d.cleanup, undeploy) + + rs, err := d.f.ClientSet.AppsV1().ReplicaSets(d.f.Namespace.Name).Get(ctx, rsName, metav1.GetOptions{}) + framework.ExpectNoError(err, "get replicaset") + + // Wait for all pods to be running. + if err := e2ereplicaset.WaitForReplicaSetTargetAvailableReplicas(d.f.ClientSet, rs, numNodes); err != nil { + framework.ExpectNoError(err, "all kubelet plugin proxies running") + } + requirement, err := labels.NewRequirement(instanceKey, selection.Equals, []string{d.Name}) + framework.ExpectNoError(err, "create label selector requirement") + selector := labels.NewSelector().Add(*requirement) + pods, err := d.f.ClientSet.CoreV1().Pods(d.f.Namespace.Name).List(ctx, metav1.ListOptions{LabelSelector: selector.String()}) + framework.ExpectNoError(err, "list proxy pods") + framework.ExpectEqual(numNodes, int32(len(pods.Items)), "number of proxy pods") + + // Run registar and plugin for each of the pods. + for _, pod := range pods.Items { + // Need a local variable, not the loop variable, for the anonymous + // callback functions below. + pod := pod + nodename := pod.Spec.NodeName + logger := klog.LoggerWithValues(klog.LoggerWithName(klog.Background(), "kubelet plugin"), "node", pod.Spec.NodeName, "pod", klog.KObj(&pod)) + plugin, err := app.StartPlugin(logger, "/cdi", d.Name, nodename, + app.FileOperations{ + Create: func(name string, content []byte) error { + ginkgo.By(fmt.Sprintf("creating CDI file %s on node %s:\n%s", name, nodename, string(content))) + return d.createFile(&pod, name, content) + }, + Remove: func(name string) error { + ginkgo.By(fmt.Sprintf("deleting CDI file %s on node %s", name, nodename)) + return d.removeFile(&pod, name) + }, + }, + kubeletplugin.GRPCVerbosity(0), + kubeletplugin.GRPCInterceptor(func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { + return d.interceptor(nodename, ctx, req, info, handler) + }), + kubeletplugin.PluginListener(listen(ctx, d.f, pod.Name, "plugin", 9001)), + kubeletplugin.RegistrarListener(listen(ctx, d.f, pod.Name, "registrar", 9000)), + kubeletplugin.KubeletPluginSocketPath(draAddr), + ) + framework.ExpectNoError(err, "start kubelet plugin for node %s", pod.Spec.NodeName) + d.cleanup = append(d.cleanup, func() { + // Depends on cancel being called first. + plugin.Stop() + }) + d.Nodes[nodename] = plugin + } + + // Wait for registration. + ginkgo.By("wait for plugin registration") + gomega.Eventually(func() []string { + var notRegistered []string + for nodename, plugin := range d.Nodes { + if !plugin.IsRegistered() { + notRegistered = append(notRegistered, nodename) + } + } + sort.Strings(notRegistered) + return notRegistered + }).WithTimeout(time.Minute).Should(gomega.BeEmpty(), "hosts where the plugin has not been registered yet") +} + +func (d *Driver) createFile(pod *v1.Pod, name string, content []byte) error { + buffer := bytes.NewBuffer(content) + // Writing the content can be slow. Better create a temporary file and + // move it to the final destination once it is complete. + tmpName := name + ".tmp" + if err := d.podIO(pod).CreateFile(tmpName, buffer); err != nil { + _ = d.podIO(pod).RemoveAll(tmpName) + return err + } + return d.podIO(pod).Rename(tmpName, name) +} + +func (d *Driver) removeFile(pod *v1.Pod, name string) error { + return d.podIO(pod).RemoveAll(name) +} + +func (d *Driver) podIO(pod *v1.Pod) proxy.PodDirIO { + logger := klog.Background() + return proxy.PodDirIO{ + F: d.f, + Namespace: pod.Namespace, + PodName: pod.Name, + ContainerName: "plugin", + Logger: &logger, + } +} + +func listen(ctx context.Context, f *framework.Framework, podName, containerName string, port int) net.Listener { + addr := proxy.Addr{ + Namespace: f.Namespace.Name, + PodName: podName, + ContainerName: containerName, + Port: port, + } + listener, err := proxy.Listen(ctx, f.ClientSet, f.ClientConfig(), addr) + framework.ExpectNoError(err, "listen for connections from %+v", addr) + return listener +} + +func (d *Driver) TearDown() { + for _, c := range d.cleanup { + c() + } + d.cleanup = nil + d.wg.Wait() +} + +func (d *Driver) interceptor(nodename string, ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { + d.mutex.Lock() + defer d.mutex.Unlock() + + m := MethodInstance{nodename, info.FullMethod} + d.callCounts[m]++ + if d.fail[m] { + return nil, errors.New("injected error") + } + + return handler(ctx, req) +} + +func (d *Driver) Fail(m MethodInstance, injectError bool) { + d.mutex.Lock() + defer d.mutex.Unlock() + + d.fail[m] = injectError +} + +func (d *Driver) CallCount(m MethodInstance) int64 { + d.mutex.Lock() + defer d.mutex.Unlock() + + return d.callCounts[m] +} + +func (d *Driver) Nodenames() (nodenames []string) { + for nodename := range d.Nodes { + nodenames = append(nodenames, nodename) + } + sort.Strings(nodenames) + return +} diff --git a/test/e2e/dra/dra.go b/test/e2e/dra/dra.go new file mode 100644 index 00000000000..ef1a3ebcba2 --- /dev/null +++ b/test/e2e/dra/dra.go @@ -0,0 +1,835 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dra + +import ( + "context" + "errors" + "fmt" + "strings" + "sync/atomic" + "time" + + "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" + + v1 "k8s.io/api/core/v1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/klog/v2" + "k8s.io/kubernetes/test/e2e/dra/test-driver/app" + "k8s.io/kubernetes/test/e2e/framework" + e2epod "k8s.io/kubernetes/test/e2e/framework/pod" + admissionapi "k8s.io/pod-security-admission/api" +) + +const ( + // podStartTimeout is how long to wait for the pod to be started. + podStartTimeout = 5 * time.Minute +) + +func networkResources() app.Resources { + return app.Resources{ + Shareable: true, + } +} + +var _ = ginkgo.Describe("[sig-node] DRA [Feature:DynamicResourceAllocation]", func() { + f := framework.NewDefaultFramework("dra") + ctx := context.Background() + + // The driver containers have to run with sufficient privileges to + // modify /var/lib/kubelet/plugins. + f.NamespacePodSecurityEnforceLevel = admissionapi.LevelPrivileged + + ginkgo.Context("kubelet", func() { + nodes := NewNodes(f, 1, 1) + driver := NewDriver(f, nodes, networkResources) // All tests get their own driver instance. + b := newBuilder(f, driver) + ginkgo.It("registers plugin", func() { + ginkgo.By("the driver is running") + }) + + // This test does not pass at the moment because kubelet doesn't retry. + ginkgo.It("must retry NodePrepareResource", func() { + // We have exactly one host. + m := MethodInstance{driver.Nodenames()[0], NodePrepareResourceMethod} + + driver.Fail(m, true) + + ginkgo.By("waiting for container startup to fail") + parameters := b.parameters() + pod, template := b.podInline(resourcev1alpha1.AllocationModeWaitForFirstConsumer) + + b.create(ctx, parameters, pod, template) + + ginkgo.By("wait for NodePrepareResource call") + gomega.Eventually(func() error { + if driver.CallCount(m) == 0 { + return errors.New("NodePrepareResource not called yet") + } + return nil + }).WithTimeout(podStartTimeout).Should(gomega.Succeed()) + + ginkgo.By("allowing container startup to succeed") + callCount := driver.CallCount(m) + driver.Fail(m, false) + err := e2epod.WaitForPodNameRunningInNamespace(f.ClientSet, pod.Name, pod.Namespace) + framework.ExpectNoError(err, "start pod with inline resource claim") + if driver.CallCount(m) == callCount { + framework.Fail("NodePrepareResource should have been called again") + } + }) + ginkgo.It("must not run a pod if a claim is not reserved for it", func() { + parameters := b.parameters() + claim := b.externalClaim(resourcev1alpha1.AllocationModeImmediate) + pod := b.podExternal() + + // This bypasses scheduling and therefore the pod gets + // to run on the node although it never gets added to + // the `ReservedFor` field of the claim. + pod.Spec.NodeName = nodes.NodeNames[0] + + b.create(ctx, parameters, claim, pod) + + gomega.Consistently(func() error { + testPod, err := b.f.ClientSet.CoreV1().Pods(pod.Namespace).Get(context.TODO(), pod.Name, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("expected the test pod %s to exist: %v", pod.Name, err) + } + if testPod.Status.Phase != v1.PodPending { + return fmt.Errorf("pod %s: unexpected status %s, expected status: %s", pod.Name, testPod.Status.Phase, v1.PodPending) + } + return nil + }, 20*time.Second, 200*time.Millisecond).Should(gomega.BeNil()) + }) + ginkgo.It("must unprepare resources for force-deleted pod", func() { + parameters := b.parameters() + claim := b.externalClaim(resourcev1alpha1.AllocationModeImmediate) + pod := b.podExternal() + zero := int64(0) + pod.Spec.TerminationGracePeriodSeconds = &zero + + b.create(ctx, parameters, claim, pod) + + b.testPod(f.ClientSet, pod) + + ginkgo.By(fmt.Sprintf("force delete test pod %s", pod.Name)) + err := b.f.ClientSet.CoreV1().Pods(b.f.Namespace.Name).Delete(ctx, pod.Name, metav1.DeleteOptions{GracePeriodSeconds: &zero}) + if !apierrors.IsNotFound(err) { + framework.ExpectNoError(err, "force delete test pod") + } + + for host, plugin := range b.driver.Nodes { + ginkgo.By(fmt.Sprintf("waiting for resources on %s to be unprepared", host)) + gomega.Eventually(plugin.GetPreparedResources).WithTimeout(time.Minute).Should(gomega.BeEmpty(), "prepared claims on host %s", host) + } + }) + }) + + ginkgo.Context("driver", func() { + nodes := NewNodes(f, 1, 1) + driver := NewDriver(f, nodes, networkResources) // All tests get their own driver instance. + b := newBuilder(f, driver) + // We need the parameters name *before* creating it. + b.parametersCounter = 1 + b.classParametersName = b.parametersName() + + ginkgo.It("supports claim and class parameters", func() { + classParameters := b.parameters("x", "y") + claimParameters := b.parameters() + pod, template := b.podInline(resourcev1alpha1.AllocationModeWaitForFirstConsumer) + + b.create(ctx, classParameters, claimParameters, pod, template) + + b.testPod(f.ClientSet, pod, "user_a", "b", "admin_x", "y") + }) + }) + + ginkgo.Context("cluster", func() { + nodes := NewNodes(f, 1, 4) + driver := NewDriver(f, nodes, networkResources) + b := newBuilder(f, driver) + + // claimTests tries out several different combinations of pods with + // claims, both inline and external. + claimTests := func(allocationMode resourcev1alpha1.AllocationMode) { + ginkgo.It("supports simple pod referencing inline resource claim", func() { + parameters := b.parameters() + pod, template := b.podInline(allocationMode) + b.create(ctx, parameters, pod, template) + + b.testPod(f.ClientSet, pod) + }) + + ginkgo.It("supports inline claim referenced by multiple containers", func() { + parameters := b.parameters() + pod, template := b.podInlineMultiple(allocationMode) + b.create(ctx, parameters, pod, template) + + b.testPod(f.ClientSet, pod) + }) + + ginkgo.It("supports simple pod referencing external resource claim", func() { + parameters := b.parameters() + pod := b.podExternal() + b.create(ctx, parameters, b.externalClaim(allocationMode), pod) + + b.testPod(f.ClientSet, pod) + }) + + ginkgo.It("supports external claim referenced by multiple pods", func() { + parameters := b.parameters() + pod1 := b.podExternal() + pod2 := b.podExternal() + pod3 := b.podExternal() + claim := b.externalClaim(allocationMode) + b.create(ctx, parameters, claim, pod1, pod2, pod3) + + for _, pod := range []*v1.Pod{pod1, pod2, pod3} { + b.testPod(f.ClientSet, pod) + } + }) + + ginkgo.It("supports external claim referenced by multiple containers of multiple pods", func() { + parameters := b.parameters() + pod1 := b.podExternalMultiple() + pod2 := b.podExternalMultiple() + pod3 := b.podExternalMultiple() + claim := b.externalClaim(allocationMode) + b.create(ctx, parameters, claim, pod1, pod2, pod3) + + for _, pod := range []*v1.Pod{pod1, pod2, pod3} { + b.testPod(f.ClientSet, pod) + } + }) + + ginkgo.It("supports init containers", func() { + parameters := b.parameters() + pod, template := b.podInline(allocationMode) + pod.Spec.InitContainers = []v1.Container{pod.Spec.Containers[0]} + pod.Spec.InitContainers[0].Name += "-init" + // This must succeed for the pod to start. + pod.Spec.InitContainers[0].Command = []string{"sh", "-c", "env | grep user_a=b"} + b.create(ctx, parameters, pod, template) + + b.testPod(f.ClientSet, pod) + }) + } + + ginkgo.Context("with delayed allocation", func() { + claimTests(resourcev1alpha1.AllocationModeWaitForFirstConsumer) + }) + + ginkgo.Context("with immediate allocation", func() { + claimTests(resourcev1alpha1.AllocationModeImmediate) + }) + }) + + ginkgo.Context("multiple nodes", func() { + nodes := NewNodes(f, 2, 8) + ginkgo.Context("with network-attached resources", func() { + driver := NewDriver(f, nodes, networkResources) + b := newBuilder(f, driver) + + ginkgo.It("schedules onto different nodes", func() { + parameters := b.parameters() + label := "app.kubernetes.io/instance" + instance := f.UniqueName + "-test-app" + antiAffinity := &v1.Affinity{ + PodAntiAffinity: &v1.PodAntiAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ + { + TopologyKey: "kubernetes.io/hostname", + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + label: instance, + }, + }, + }, + }, + }, + } + createPod := func() *v1.Pod { + pod := b.podExternal() + pod.Labels[label] = instance + pod.Spec.Affinity = antiAffinity + return pod + } + pod1 := createPod() + pod2 := createPod() + claim := b.externalClaim(resourcev1alpha1.AllocationModeWaitForFirstConsumer) + b.create(ctx, parameters, claim, pod1, pod2) + + for _, pod := range []*v1.Pod{pod1, pod2} { + err := e2epod.WaitForPodRunningInNamespace(f.ClientSet, pod) + framework.ExpectNoError(err, "start pod") + } + }) + }) + + ginkgo.Context("with node-local resources", func() { + driver := NewDriver(f, nodes, func() app.Resources { + return app.Resources{ + NodeLocal: true, + MaxAllocations: 1, + Nodes: nodes.NodeNames, + } + }) + b := newBuilder(f, driver) + + tests := func(allocationMode resourcev1alpha1.AllocationMode) { + ginkgo.It("uses all resources", func() { + var objs = []klog.KMetadata{ + b.parameters(), + } + var pods []*v1.Pod + for i := 0; i < len(nodes.NodeNames); i++ { + pod, template := b.podInline(allocationMode) + pods = append(pods, pod) + objs = append(objs, pod, template) + } + b.create(ctx, objs...) + + for _, pod := range pods { + err := e2epod.WaitForPodRunningInNamespace(f.ClientSet, pod) + framework.ExpectNoError(err, "start pod") + } + + // The pods all should run on different + // nodes because the maximum number of + // claims per node was limited to 1 for + // this test. + // + // We cannot know for sure why the pods + // ran on two different nodes (could + // also be a coincidence) but if they + // don't cover all nodes, then we have + // a problem. + used := make(map[string]*v1.Pod) + for _, pod := range pods { + pod, err := f.ClientSet.CoreV1().Pods(pod.Namespace).Get(ctx, pod.Name, metav1.GetOptions{}) + framework.ExpectNoError(err, "get pod") + nodeName := pod.Spec.NodeName + if other, ok := used[nodeName]; ok { + framework.Failf("Pod %s got started on the same node %s as pod %s although claim allocation should have been limited to one claim per node.", pod.Name, nodeName, other.Name) + } + used[nodeName] = pod + } + }) + } + + ginkgo.Context("with delayed allocation", func() { + tests(resourcev1alpha1.AllocationModeWaitForFirstConsumer) + }) + + ginkgo.Context("with immediate allocation", func() { + tests(resourcev1alpha1.AllocationModeImmediate) + }) + }) + + ginkgo.Context("reallocation", func() { + var allocateWrapper app.AllocateWrapperType + driver := NewDriver(f, nodes, func() app.Resources { + return app.Resources{ + NodeLocal: true, + MaxAllocations: 2, + Nodes: nodes.NodeNames, + + AllocateWrapper: func(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, claimParameters interface{}, class *resourcev1alpha1.ResourceClass, classParameters interface{}, selectedNode string, + handler func(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, claimParameters interface{}, class *resourcev1alpha1.ResourceClass, classParameters interface{}, selectedNode string) (result *resourcev1alpha1.AllocationResult, err error)) (result *resourcev1alpha1.AllocationResult, err error) { + return allocateWrapper(ctx, claim, claimParameters, class, classParameters, selectedNode, handler) + }, + } + }) + b := newBuilder(f, driver) + + ginkgo.It("works", func() { + // A pod with two claims can run on a node, but + // only if allocation of both succeeds. This + // tests simulates the scenario where one claim + // gets allocated but the second doesn't + // because of a race with some other pod. + // + // To ensure the right timing, allocation of the second + // claim gets delayed while creating another pod + // that gets the remaining resource on the node. + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + parameters := b.parameters() + claim1 := b.externalClaim(resourcev1alpha1.AllocationModeWaitForFirstConsumer) + claim2 := b.externalClaim(resourcev1alpha1.AllocationModeWaitForFirstConsumer) + pod1 := b.podExternal() + pod1.Spec.ResourceClaims = append(pod1.Spec.ResourceClaims, + v1.PodResourceClaim{ + Name: "claim2", + Source: v1.ClaimSource{ + ResourceClaimName: &claim2.Name, + }, + }, + ) + + // Block on the second external claim that is to be allocated. + blockClaim, cancelBlockClaim := context.WithCancel(ctx) + defer cancelBlockClaim() + var allocated int32 + allocateWrapper = func(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, claimParameters interface{}, + class *resourcev1alpha1.ResourceClass, classParameters interface{}, selectedNode string, + handler func(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, claimParameters interface{}, + class *resourcev1alpha1.ResourceClass, classParameters interface{}, selectedNode string) (result *resourcev1alpha1.AllocationResult, err error), + ) (result *resourcev1alpha1.AllocationResult, err error) { + oldAllocated := atomic.AddInt32(&allocated, 0) + if oldAllocated == 1 && strings.HasPrefix(claim.Name, "external-claim") { + <-blockClaim.Done() + } + result, err = handler(ctx, claim, claimParameters, class, classParameters, selectedNode) + if err == nil { + atomic.AddInt32(&allocated, 1) + } + return + } + b.create(ctx, parameters, claim1, claim2, pod1) + + ginkgo.By("waiting for one claim to be allocated") + var nodeSelector *v1.NodeSelector + gomega.Eventually(func() (int, error) { + claims, err := f.ClientSet.ResourceV1alpha1().ResourceClaims(f.Namespace.Name).List(ctx, metav1.ListOptions{}) + if err != nil { + return 0, err + } + allocated := 0 + for _, claim := range claims.Items { + if claim.Status.Allocation != nil { + allocated++ + nodeSelector = claim.Status.Allocation.AvailableOnNodes + } + } + return allocated, nil + }).WithTimeout(time.Minute).Should(gomega.Equal(1), "one claim allocated") + + // Now create a second pod which we force to + // run on the same node that is currently being + // considered for the first one. We know what + // the node selector looks like and can + // directly access the key and value from it. + ginkgo.By(fmt.Sprintf("create second pod on the same node %s", nodeSelector)) + pod2, template2 := b.podInline(resourcev1alpha1.AllocationModeWaitForFirstConsumer) + req := nodeSelector.NodeSelectorTerms[0].MatchExpressions[0] + node := req.Values[0] + pod2.Spec.NodeSelector = map[string]string{req.Key: node} + b.create(ctx, pod2, template2) + framework.ExpectNoError(e2epod.WaitForPodRunningInNamespace(f.ClientSet, pod2), "start pod 2") + + // Allow allocation of claim2 to proceed. It should fail now + // and the other node must be used instead, after deallocating + // the first claim. + ginkgo.By("move first pod to other node") + cancelBlockClaim() + framework.ExpectNoError(e2epod.WaitForPodRunningInNamespace(f.ClientSet, pod1), "start pod 1") + pod1, err := f.ClientSet.CoreV1().Pods(pod1.Namespace).Get(ctx, pod1.Name, metav1.GetOptions{}) + framework.ExpectNoError(err, "get first pod") + if pod1.Spec.NodeName == "" { + framework.Fail("first pod should be running on node, was not scheduled") + } + framework.ExpectNotEqual(pod1.Spec.NodeName, node, "first pod should run on different node than second one") + framework.ExpectEqual(driver.Controller.GetNumDeallocations(), int64(1), "number of deallocations") + }) + }) + }) + + ginkgo.Context("multiple drivers", func() { + nodes := NewNodes(f, 1, 4) + driver1 := NewDriver(f, nodes, func() app.Resources { + return app.Resources{ + NodeLocal: true, + MaxAllocations: 1, + Nodes: nodes.NodeNames, + } + }) + b1 := newBuilder(f, driver1) + driver2 := NewDriver(f, nodes, func() app.Resources { + return app.Resources{ + NodeLocal: true, + MaxAllocations: 1, + Nodes: nodes.NodeNames, + } + }) + driver2.NameSuffix = "-other" + b2 := newBuilder(f, driver2) + + ginkgo.It("work", func() { + parameters1 := b1.parameters() + parameters2 := b2.parameters() + claim1 := b1.externalClaim(resourcev1alpha1.AllocationModeWaitForFirstConsumer) + claim2 := b2.externalClaim(resourcev1alpha1.AllocationModeWaitForFirstConsumer) + pod := b1.podExternal() + pod.Spec.ResourceClaims = append(pod.Spec.ResourceClaims, + v1.PodResourceClaim{ + Name: "claim2", + Source: v1.ClaimSource{ + ResourceClaimName: &claim2.Name, + }, + }, + ) + b1.create(ctx, parameters1, parameters2, claim1, claim2, pod) + b1.testPod(f.ClientSet, pod) + }) + }) +}) + +// builder contains a running counter to make objects unique within thir +// namespace. +type builder struct { + f *framework.Framework + driver *Driver + + podCounter int + parametersCounter int + claimCounter int + + classParametersName string +} + +// className returns the default resource class name. +func (b *builder) className() string { + return b.f.UniqueName + b.driver.NameSuffix + "-class" +} + +// class returns the resource class that the builder's other objects +// reference. +func (b *builder) class() *resourcev1alpha1.ResourceClass { + class := &resourcev1alpha1.ResourceClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.className(), + }, + DriverName: b.driver.Name, + SuitableNodes: b.nodeSelector(), + } + if b.classParametersName != "" { + class.ParametersRef = &resourcev1alpha1.ResourceClassParametersReference{ + Kind: "ConfigMap", + Name: b.classParametersName, + Namespace: b.f.Namespace.Name, + } + } + return class +} + +// nodeSelector returns a node selector that matches all nodes on which the +// kubelet plugin was deployed. +func (b *builder) nodeSelector() *v1.NodeSelector { + return &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "kubernetes.io/hostname", + Operator: v1.NodeSelectorOpIn, + Values: b.driver.Nodenames(), + }, + }, + }, + }, + } +} + +// externalClaim returns external resource claim +// that test pods can reference +func (b *builder) externalClaim(allocationMode resourcev1alpha1.AllocationMode) *resourcev1alpha1.ResourceClaim { + b.claimCounter++ + name := "external-claim" + b.driver.NameSuffix // This is what podExternal expects. + if b.claimCounter > 1 { + name += fmt.Sprintf("-%d", b.claimCounter) + } + return &resourcev1alpha1.ResourceClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: resourcev1alpha1.ResourceClaimSpec{ + ResourceClassName: b.className(), + ParametersRef: &resourcev1alpha1.ResourceClaimParametersReference{ + Kind: "ConfigMap", + Name: b.parametersName(), + }, + AllocationMode: allocationMode, + }, + } +} + +// parametersName returns the current ConfigMap name for resource +// claim or class parameters. +func (b *builder) parametersName() string { + return fmt.Sprintf("parameters%s-%d", b.driver.NameSuffix, b.parametersCounter) +} + +// parametersEnv returns the default env variables. +func (b *builder) parametersEnv() map[string]string { + return map[string]string{ + "a": "b", + } +} + +// parameters returns a config map with the default env variables. +func (b *builder) parameters(kv ...string) *v1.ConfigMap { + b.parametersCounter++ + data := map[string]string{} + for i := 0; i < len(kv); i += 2 { + data[kv[i]] = kv[i+1] + } + if len(data) == 0 { + data = b.parametersEnv() + } + return &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: b.f.Namespace.Name, + Name: b.parametersName(), + }, + Data: data, + } +} + +// makePod returns a simple pod with no resource claims. +// The pod prints its env and waits. +func (b *builder) pod() *v1.Pod { + pod := e2epod.MakePod(b.f.Namespace.Name, nil, nil, false, "env && sleep 100000") + pod.Labels = make(map[string]string) + pod.Spec.RestartPolicy = v1.RestartPolicyNever + // Let kubelet kill the pods quickly. Setting + // TerminationGracePeriodSeconds to zero would bypass kubelet + // completely because then the apiserver enables a force-delete even + // when DeleteOptions for the pod don't ask for it (see + // https://github.com/kubernetes/kubernetes/blob/0f582f7c3f504e807550310d00f130cb5c18c0c3/pkg/registry/core/pod/strategy.go#L151-L171). + // + // We don't do that because it breaks tracking of claim usage: the + // kube-controller-manager assumes that kubelet is done with the pod + // once it got removed or has a grace period of 0. Setting the grace + // period to zero directly in DeletionOptions or indirectly through + // TerminationGracePeriodSeconds causes the controller to remove + // the pod from ReservedFor before it actually has stopped on + // the node. + one := int64(1) + pod.Spec.TerminationGracePeriodSeconds = &one + pod.ObjectMeta.GenerateName = "" + b.podCounter++ + pod.ObjectMeta.Name = fmt.Sprintf("tester%s-%d", b.driver.NameSuffix, b.podCounter) + return pod +} + +// makePodInline adds an inline resource claim with default class name and parameters. +func (b *builder) podInline(allocationMode resourcev1alpha1.AllocationMode) (*v1.Pod, *resourcev1alpha1.ResourceClaimTemplate) { + pod := b.pod() + pod.Spec.Containers[0].Name = "with-resource" + podClaimName := "my-inline-claim" + pod.Spec.Containers[0].Resources.Claims = []v1.ResourceClaim{{Name: podClaimName}} + pod.Spec.ResourceClaims = []v1.PodResourceClaim{ + { + Name: podClaimName, + Source: v1.ClaimSource{ + ResourceClaimTemplateName: &pod.Name, + }, + }, + } + template := &resourcev1alpha1.ResourceClaimTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Name: pod.Name, + Namespace: pod.Namespace, + }, + Spec: resourcev1alpha1.ResourceClaimTemplateSpec{ + Spec: resourcev1alpha1.ResourceClaimSpec{ + ResourceClassName: b.className(), + ParametersRef: &resourcev1alpha1.ResourceClaimParametersReference{ + Kind: "ConfigMap", + Name: b.parametersName(), + }, + AllocationMode: allocationMode, + }, + }, + } + return pod, template +} + +// podInlineMultiple returns a pod with inline resource claim referenced by 3 containers +func (b *builder) podInlineMultiple(allocationMode resourcev1alpha1.AllocationMode) (*v1.Pod, *resourcev1alpha1.ResourceClaimTemplate) { + pod, template := b.podInline(allocationMode) + pod.Spec.Containers = append(pod.Spec.Containers, *pod.Spec.Containers[0].DeepCopy(), *pod.Spec.Containers[0].DeepCopy()) + pod.Spec.Containers[1].Name = pod.Spec.Containers[1].Name + "-1" + pod.Spec.Containers[2].Name = pod.Spec.Containers[1].Name + "-2" + return pod, template +} + +// podExternal adds a pod that references external resource claim with default class name and parameters. +func (b *builder) podExternal() *v1.Pod { + pod := b.pod() + pod.Spec.Containers[0].Name = "with-resource" + podClaimName := "resource-claim" + externalClaimName := "external-claim" + b.driver.NameSuffix + pod.Spec.ResourceClaims = []v1.PodResourceClaim{ + { + Name: podClaimName, + Source: v1.ClaimSource{ + ResourceClaimName: &externalClaimName, + }, + }, + } + pod.Spec.Containers[0].Resources.Claims = []v1.ResourceClaim{{Name: podClaimName}} + return pod +} + +// podShared returns a pod with 3 containers that reference external resource claim with default class name and parameters. +func (b *builder) podExternalMultiple() *v1.Pod { + pod := b.podExternal() + pod.Spec.Containers = append(pod.Spec.Containers, *pod.Spec.Containers[0].DeepCopy(), *pod.Spec.Containers[0].DeepCopy()) + pod.Spec.Containers[1].Name = pod.Spec.Containers[1].Name + "-1" + pod.Spec.Containers[2].Name = pod.Spec.Containers[1].Name + "-2" + return pod +} + +// create takes a bunch of objects and calls their Create function. +func (b *builder) create(ctx context.Context, objs ...klog.KMetadata) { + for _, obj := range objs { + ginkgo.By(fmt.Sprintf("creating %T %s", obj, obj.GetName()), func() { + var err error + switch obj := obj.(type) { + case *resourcev1alpha1.ResourceClass: + _, err = b.f.ClientSet.ResourceV1alpha1().ResourceClasses().Create(ctx, obj, metav1.CreateOptions{}) + case *v1.Pod: + _, err = b.f.ClientSet.CoreV1().Pods(b.f.Namespace.Name).Create(ctx, obj, metav1.CreateOptions{}) + case *v1.ConfigMap: + _, err = b.f.ClientSet.CoreV1().ConfigMaps(b.f.Namespace.Name).Create(ctx, obj, metav1.CreateOptions{}) + case *resourcev1alpha1.ResourceClaim: + _, err = b.f.ClientSet.ResourceV1alpha1().ResourceClaims(b.f.Namespace.Name).Create(ctx, obj, metav1.CreateOptions{}) + case *resourcev1alpha1.ResourceClaimTemplate: + _, err = b.f.ClientSet.ResourceV1alpha1().ResourceClaimTemplates(b.f.Namespace.Name).Create(ctx, obj, metav1.CreateOptions{}) + default: + framework.Fail(fmt.Sprintf("internal error, unsupported type %T", obj), 1) + } + framework.ExpectNoErrorWithOffset(1, err, "create %T", obj) + }) + } +} + +// testPod runs pod and checks if container logs contain expected environment variables +func (b *builder) testPod(clientSet kubernetes.Interface, pod *v1.Pod, env ...string) { + err := e2epod.WaitForPodRunningInNamespace(clientSet, pod) + framework.ExpectNoError(err, "start pod") + + for _, container := range pod.Spec.Containers { + log, err := e2epod.GetPodLogs(clientSet, pod.Namespace, pod.Name, container.Name) + framework.ExpectNoError(err, "get logs") + if len(env) == 0 { + for key, value := range b.parametersEnv() { + envStr := fmt.Sprintf("\nuser_%s=%s\n", key, value) + gomega.Expect(log).To(gomega.ContainSubstring(envStr), "container env variables") + } + } else { + for i := 0; i < len(env); i += 2 { + envStr := fmt.Sprintf("\n%s=%s\n", env[i], env[i+1]) + gomega.Expect(log).To(gomega.ContainSubstring(envStr), "container env variables") + } + } + } +} + +func newBuilder(f *framework.Framework, driver *Driver) *builder { + b := &builder{f: f, driver: driver} + + ginkgo.BeforeEach(b.setUp) + + return b +} + +func (b *builder) setUp() { + b.podCounter = 0 + b.parametersCounter = 0 + b.claimCounter = 0 + b.create(context.Background(), b.class()) + ginkgo.DeferCleanup(b.tearDown) +} + +func (b *builder) tearDown() { + ctx := context.Background() + + err := b.f.ClientSet.ResourceV1alpha1().ResourceClasses().Delete(ctx, b.className(), metav1.DeleteOptions{}) + framework.ExpectNoError(err, "delete resource class") + + // Before we allow the namespace and all objects in it do be deleted by + // the framework, we must ensure that test pods and the claims that + // they use are deleted. Otherwise the driver might get deleted first, + // in which case deleting the claims won't work anymore. + ginkgo.By("delete pods and claims") + pods, err := b.listTestPods(ctx) + framework.ExpectNoError(err, "list pods") + for _, pod := range pods { + if pod.DeletionTimestamp != nil { + continue + } + ginkgo.By(fmt.Sprintf("deleting %T %s", &pod, klog.KObj(&pod))) + err := b.f.ClientSet.CoreV1().Pods(b.f.Namespace.Name).Delete(ctx, pod.Name, metav1.DeleteOptions{}) + if !apierrors.IsNotFound(err) { + framework.ExpectNoError(err, "delete pod") + } + } + gomega.Eventually(func() ([]v1.Pod, error) { + return b.listTestPods(ctx) + }).WithTimeout(time.Minute).Should(gomega.BeEmpty(), "remaining pods despite deletion") + + claims, err := b.f.ClientSet.ResourceV1alpha1().ResourceClaims(b.f.Namespace.Name).List(ctx, metav1.ListOptions{}) + framework.ExpectNoError(err, "get resource claims") + for _, claim := range claims.Items { + if claim.DeletionTimestamp != nil { + continue + } + ginkgo.By(fmt.Sprintf("deleting %T %s", &claim, klog.KObj(&claim))) + err := b.f.ClientSet.ResourceV1alpha1().ResourceClaims(b.f.Namespace.Name).Delete(ctx, claim.Name, metav1.DeleteOptions{}) + if !apierrors.IsNotFound(err) { + framework.ExpectNoError(err, "delete claim") + } + } + + for host, plugin := range b.driver.Nodes { + ginkgo.By(fmt.Sprintf("waiting for resources on %s to be unprepared", host)) + gomega.Eventually(plugin.GetPreparedResources).WithTimeout(time.Minute).Should(gomega.BeEmpty(), "prepared claims on host %s", host) + } + + ginkgo.By("waiting for claims to be deallocated and deleted") + gomega.Eventually(func() ([]resourcev1alpha1.ResourceClaim, error) { + claims, err := b.f.ClientSet.ResourceV1alpha1().ResourceClaims(b.f.Namespace.Name).List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, err + } + return claims.Items, nil + }).WithTimeout(time.Minute).Should(gomega.BeEmpty(), "claims in the namespaces") +} + +func (b *builder) listTestPods(ctx context.Context) ([]v1.Pod, error) { + pods, err := b.f.ClientSet.CoreV1().Pods(b.f.Namespace.Name).List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, err + } + + var testPods []v1.Pod + for _, pod := range pods.Items { + if pod.Labels["app.kubernetes.io/part-of"] == "dra-test-driver" { + continue + } + testPods = append(testPods, pod) + } + return testPods, nil +} diff --git a/test/e2e/dra/kind-build-image.sh b/test/e2e/dra/kind-build-image.sh new file mode 100755 index 00000000000..f935f50a06e --- /dev/null +++ b/test/e2e/dra/kind-build-image.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +# Copyright 2022 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This scripts invokes `kind build image` so that the resulting +# image has a containerd with CDI support. +# +# Usage: kind-build-image.sh + +set -ex +set -o pipefail + +tag="$1" +containerd="containerd-1.6.0-830-g34d078e99" # from https://github.com/kind-ci/containerd-nightlies/releases + +tmpdir="$(mktemp -d)" +cleanup() { + rm -rf "$tmpdir" +} +trap cleanup EXIT + +kind build node-image --image "$tag" "$(pwd)" +curl -L --silent https://github.com/kind-ci/containerd-nightlies/releases/download/$containerd/$containerd-linux-amd64.tar.gz | tar -C "$tmpdir" -vzxf - +curl -L --silent https://github.com/kind-ci/containerd-nightlies/releases/download/$containerd/runc.amd64 >"$tmpdir/runc" + +cat >"$tmpdir/Dockerfile" <dynamic resource allocation plugin interaction. + +`app` is the driver itself with a very simple implementation of the interfaces. + +## Deployment + +### `local-up-cluster.sh` + +To try out the feature, build Kubernetes, then in one console run: +```console +FEATURE_GATES=DynamicResourceAllocation=true ALLOW_PRIVILEGED=1 ./hack/local-up-cluster.sh -O +``` + +In another: +```console +go run ./test/e2e/dra/test-driver --feature-gates ContextualLogging=true -v=5 controller +``` + +In yet another: +```console +sudo mkdir -p /var/run/cdi && sudo chmod a+rwx /var/run/cdi /var/lib/kubelet/plugins_registry +go run ./test/e2e/dra/test-driver --feature-gates ContextualLogging=true -v=5 kubelet-plugin +``` + +And finally: +```console +$ kubectl create -f test/e2e/dra/test-driver/deploy/example/resourceclass.yaml +resourceclass/example created +$ kubectl create -f test/e2e/dra/test-driver/deploy/example/pod-inline.yaml +configmap/pause-claim-parameters created +pod/pause created + +$ kubectl get resourceclaims +NAME CLASSNAME ALLOCATIONMODE STATE AGE +pause-resource example WaitForFirstConsumer allocated,reserved 19s + +$ kubectl get pods +NAME READY STATUS RESTARTS AGE +pause 1/1 Running 0 23s +``` + +There are also examples for other scenarios (multiple pods, multiple claims). + +### multi-node cluster + +At this point there are no container images that contain the test driver and +therefore it cannot be deployed on "normal" clusters. + +## Prior art + +Some of this code was derived from the +[external-resizer](https://github.com/kubernetes-csi/external-resizer/). `controller` +corresponds to the [controller +logic](https://github.com/kubernetes-csi/external-resizer/blob/master/pkg/controller/controller.go), +which in turn is similar to the +[sig-storage-lib-external-provisioner](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner). diff --git a/test/e2e/dra/test-driver/app/cdi.go b/test/e2e/dra/test-driver/app/cdi.go new file mode 100644 index 00000000000..41d1976c8a7 --- /dev/null +++ b/test/e2e/dra/test-driver/app/cdi.go @@ -0,0 +1,44 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package app + +// These definitions are sufficient to generate simple CDI files which set env +// variables in a container, which is all that the test driver does. A real +// driver will either use pre-generated CDI files or can use the +// github.com/container-orchestrated-devices/container-device-interface/pkg/cdi +// helper package to generate files. +// +// This is not done in Kubernetes to minimize dependencies. + +// spec is the base configuration for CDI. +type spec struct { + Version string `json:"cdiVersion"` + Kind string `json:"kind"` + + Devices []device `json:"devices"` +} + +// device is a "Device" a container runtime can add to a container. +type device struct { + Name string `json:"name"` + ContainerEdits containerEdits `json:"containerEdits"` +} + +// containerEdits are edits a container runtime must make to the OCI spec to expose the device. +type containerEdits struct { + Env []string `json:"env,omitempty"` +} diff --git a/test/e2e/dra/test-driver/app/controller.go b/test/e2e/dra/test-driver/app/controller.go new file mode 100644 index 00000000000..079e7739dcf --- /dev/null +++ b/test/e2e/dra/test-driver/app/controller.go @@ -0,0 +1,357 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package app does all of the work necessary to configure and run a +// Kubernetes app process. +package app + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "math/rand" + "strings" + "sync" + + v1 "k8s.io/api/core/v1" + resourcev1alpha1 "k8s.io/api/resource/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + "k8s.io/dynamic-resource-allocation/controller" + "k8s.io/klog/v2" +) + +type Resources struct { + NodeLocal bool + Nodes []string + MaxAllocations int + Shareable bool + + // AllocateWrapper, if set, gets called for each Allocate call. + AllocateWrapper AllocateWrapperType +} + +type AllocateWrapperType func(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, claimParameters interface{}, + class *resourcev1alpha1.ResourceClass, classParameters interface{}, selectedNode string, + handler func(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, claimParameters interface{}, + class *resourcev1alpha1.ResourceClass, classParameters interface{}, selectedNode string) (result *resourcev1alpha1.AllocationResult, err error), +) (result *resourcev1alpha1.AllocationResult, err error) + +type ExampleController struct { + clientset kubernetes.Interface + resources Resources + driverName string + + // mutex must be locked at the gRPC call level. + mutex sync.Mutex + // allocated maps claim.UID to the node (if network-attached) or empty (if not). + allocated map[types.UID]string + + numAllocations, numDeallocations int64 +} + +func NewController(clientset kubernetes.Interface, driverName string, resources Resources) *ExampleController { + c := &ExampleController{ + clientset: clientset, + resources: resources, + driverName: driverName, + + allocated: make(map[types.UID]string), + } + return c +} + +func (c *ExampleController) Run(ctx context.Context, workers int) *ExampleController { + informerFactory := informers.NewSharedInformerFactory(c.clientset, 0 /* resync period */) + ctrl := controller.New(ctx, c.driverName, c, c.clientset, informerFactory) + informerFactory.Start(ctx.Done()) + ctrl.Run(workers) + + return c +} + +type parameters struct { + EnvVars map[string]string + NodeName string +} + +var _ controller.Driver = &ExampleController{} + +func (c *ExampleController) countAllocations(node string) int { + total := 0 + for _, n := range c.allocated { + if n == node { + total++ + } + } + return total +} + +// GetNumAllocations returns the number of times that a claim was allocated. +// Idempotent calls to Allocate that do not need to allocate the claim again do +// not contribute to that counter. +func (c *ExampleController) GetNumAllocations() int64 { + c.mutex.Lock() + defer c.mutex.Unlock() + + return c.numAllocations +} + +// GetNumDeallocations returns the number of times that a claim was allocated. +// Idempotent calls to Allocate that do not need to allocate the claim again do +// not contribute to that counter. +func (c *ExampleController) GetNumDeallocations() int64 { + c.mutex.Lock() + defer c.mutex.Unlock() + + return c.numDeallocations +} + +func (c *ExampleController) GetClassParameters(ctx context.Context, class *resourcev1alpha1.ResourceClass) (interface{}, error) { + if class.ParametersRef != nil { + if class.ParametersRef.APIGroup != "" || + class.ParametersRef.Kind != "ConfigMap" { + return nil, fmt.Errorf("class parameters are only supported in APIVersion v1, Kind ConfigMap, got: %v", class.ParametersRef) + } + return c.readParametersFromConfigMap(ctx, class.ParametersRef.Namespace, class.ParametersRef.Name) + } + return nil, nil +} + +func (c *ExampleController) GetClaimParameters(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, class *resourcev1alpha1.ResourceClass, classParameters interface{}) (interface{}, error) { + if claim.Spec.ParametersRef != nil { + if claim.Spec.ParametersRef.APIGroup != "" || + claim.Spec.ParametersRef.Kind != "ConfigMap" { + return nil, fmt.Errorf("claim parameters are only supported in APIVersion v1, Kind ConfigMap, got: %v", claim.Spec.ParametersRef) + } + return c.readParametersFromConfigMap(ctx, claim.Namespace, claim.Spec.ParametersRef.Name) + } + return nil, nil +} + +func (c *ExampleController) readParametersFromConfigMap(ctx context.Context, namespace, name string) (map[string]string, error) { + configMap, err := c.clientset.CoreV1().ConfigMaps(namespace).Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return nil, fmt.Errorf("get config map: %v", err) + } + return configMap.Data, nil +} + +func (c *ExampleController) Allocate(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, claimParameters interface{}, class *resourcev1alpha1.ResourceClass, classParameters interface{}, selectedNode string) (result *resourcev1alpha1.AllocationResult, err error) { + if c.resources.AllocateWrapper != nil { + return c.resources.AllocateWrapper(ctx, claim, claimParameters, class, classParameters, selectedNode, c.allocate) + } + return c.allocate(ctx, claim, claimParameters, class, classParameters, selectedNode) +} + +// allocate simply copies parameters as JSON map into ResourceHandle. +func (c *ExampleController) allocate(ctx context.Context, claim *resourcev1alpha1.ResourceClaim, claimParameters interface{}, class *resourcev1alpha1.ResourceClass, classParameters interface{}, selectedNode string) (result *resourcev1alpha1.AllocationResult, err error) { + logger := klog.LoggerWithValues(klog.LoggerWithName(klog.FromContext(ctx), "Allocate"), "claim", klog.KObj(claim), "uid", claim.UID) + defer func() { + logger.Info("done", "result", prettyPrint(result), "err", err) + }() + + c.mutex.Lock() + defer c.mutex.Unlock() + + // Already allocated? Then we don't need to count it again. + node, alreadyAllocated := c.allocated[claim.UID] + if alreadyAllocated { + // Idempotent result - kind of. We don't check whether + // the parameters changed in the meantime. A real + // driver would have to do that. + logger.Info("already allocated") + } else { + logger.Info("starting", "selectedNode", selectedNode) + if c.resources.NodeLocal { + node = selectedNode + if node == "" { + // If none has been selected because we do immediate allocation, + // then we need to pick one ourselves. + var viableNodes []string + for _, n := range c.resources.Nodes { + if c.resources.MaxAllocations == 0 || + c.countAllocations(n) < c.resources.MaxAllocations { + viableNodes = append(viableNodes, n) + } + } + if len(viableNodes) == 0 { + return nil, errors.New("resources exhausted on all nodes") + } + // Pick randomly. We could also prefer the one with the least + // number of allocations (even spreading) or the most (packing). + node = viableNodes[rand.Intn(len(viableNodes))] + logger.Info("picked a node ourselves", "selectedNode", selectedNode) + } else if c.resources.MaxAllocations > 0 && + c.countAllocations(node) >= c.resources.MaxAllocations { + return nil, fmt.Errorf("resources exhausted on node %q", node) + } + } else { + if c.resources.MaxAllocations > 0 && + len(c.allocated) >= c.resources.MaxAllocations { + return nil, errors.New("resources exhausted in the cluster") + } + } + } + + allocation := &resourcev1alpha1.AllocationResult{ + Shareable: c.resources.Shareable, + } + p := parameters{ + EnvVars: make(map[string]string), + NodeName: node, + } + toEnvVars("user", claimParameters, p.EnvVars) + toEnvVars("admin", classParameters, p.EnvVars) + data, err := json.Marshal(p) + if err != nil { + return nil, fmt.Errorf("encode parameters: %v", err) + } + allocation.ResourceHandle = string(data) + var nodes []string + if node != "" { + nodes = append(nodes, node) + } else { + nodes = c.resources.Nodes + } + if len(nodes) > 0 { + allocation.AvailableOnNodes = &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + { + MatchExpressions: []v1.NodeSelectorRequirement{ + { + Key: "kubernetes.io/hostname", + Operator: v1.NodeSelectorOpIn, + Values: nodes, + }, + }, + }, + }, + } + } + if !alreadyAllocated { + c.numAllocations++ + c.allocated[claim.UID] = node + } + return allocation, nil +} + +func (c *ExampleController) Deallocate(ctx context.Context, claim *resourcev1alpha1.ResourceClaim) error { + logger := klog.LoggerWithValues(klog.LoggerWithName(klog.FromContext(ctx), "Deallocate"), "claim", klog.KObj(claim), "uid", claim.UID) + c.mutex.Lock() + defer c.mutex.Unlock() + + if _, ok := c.allocated[claim.UID]; !ok { + logger.Info("already deallocated") + return nil + } + + logger.Info("done") + c.numDeallocations++ + delete(c.allocated, claim.UID) + return nil +} + +func (c *ExampleController) UnsuitableNodes(ctx context.Context, pod *v1.Pod, claims []*controller.ClaimAllocation, potentialNodes []string) (finalErr error) { + logger := klog.LoggerWithValues(klog.LoggerWithName(klog.FromContext(ctx), "UnsuitableNodes"), "pod", klog.KObj(pod)) + logger.Info("starting", "claim", prettyPrintSlice(claims), "potentialNodes", potentialNodes) + defer func() { + // UnsuitableNodes is the same for all claims. + logger.Info("done", "unsuitableNodes", claims[0].UnsuitableNodes, "err", finalErr) + }() + if c.resources.MaxAllocations == 0 { + // All nodes are suitable. + return nil + } + if c.resources.NodeLocal { + allocationsPerNode := make(map[string]int) + for _, node := range c.resources.Nodes { + allocationsPerNode[node] = c.countAllocations(node) + } + for _, claim := range claims { + claim.UnsuitableNodes = nil + for _, node := range potentialNodes { + // If we have more than one claim, then a + // single pod wants to use all of them. That + // can only work if a node has capacity left + // for all of them. Also, nodes that the driver + // doesn't run on cannot be used. + if contains(c.resources.Nodes, node) && + allocationsPerNode[node]+len(claims) > c.resources.MaxAllocations { + claim.UnsuitableNodes = append(claim.UnsuitableNodes, node) + } + } + } + return nil + } + + allocations := c.countAllocations("") + for _, claim := range claims { + claim.UnsuitableNodes = nil + for _, node := range potentialNodes { + if contains(c.resources.Nodes, node) && + allocations+len(claims) > c.resources.MaxAllocations { + claim.UnsuitableNodes = append(claim.UnsuitableNodes, node) + } + } + } + + return nil +} + +func toEnvVars(what string, from interface{}, to map[string]string) { + if from == nil { + return + } + + env := from.(map[string]string) + for key, value := range env { + to[what+"_"+strings.ToLower(key)] = value + } +} + +func contains[T comparable](list []T, value T) bool { + for _, v := range list { + if v == value { + return true + } + } + + return false +} + +func prettyPrint[T any](obj *T) interface{} { + if obj == nil { + return "" + } + return *obj +} + +// prettyPrintSlice prints the values the slice points to, not the pointers. +func prettyPrintSlice[T any](slice []*T) interface{} { + var values []interface{} + for _, v := range slice { + if v == nil { + values = append(values, "") + } else { + values = append(values, *v) + } + } + return values +} diff --git a/test/e2e/dra/test-driver/app/kubeletplugin.go b/test/e2e/dra/test-driver/app/kubeletplugin.go new file mode 100644 index 00000000000..89e9b85734b --- /dev/null +++ b/test/e2e/dra/test-driver/app/kubeletplugin.go @@ -0,0 +1,208 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package app + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "sync" + + "k8s.io/dynamic-resource-allocation/kubeletplugin" + "k8s.io/klog/v2" + drapbv1 "k8s.io/kubelet/pkg/apis/dra/v1alpha1" +) + +type ExamplePlugin struct { + logger klog.Logger + d kubeletplugin.DRAPlugin + fileOps FileOperations + + cdiDir string + driverName string + nodeName string + + mutex sync.Mutex + prepared map[ClaimID]bool +} + +// ClaimID contains both claim name and UID to simplify debugging. The +// namespace is not included because it is random in E2E tests and the UID is +// sufficient to make the ClaimID unique. +type ClaimID struct { + Name string + UID string +} + +var _ drapbv1.NodeServer = &ExamplePlugin{} + +// getJSONFilePath returns the absolute path where CDI file is/should be. +func (ex *ExamplePlugin) getJSONFilePath(claimUID string) string { + return filepath.Join(ex.cdiDir, fmt.Sprintf("%s-%s.json", ex.driverName, claimUID)) +} + +// FileOperations defines optional callbacks for handling CDI files. +type FileOperations struct { + // Create must overwrite the file. + Create func(name string, content []byte) error + + // Remove must remove the file. It must not return an error when the + // file does not exist. + Remove func(name string) error +} + +// StartPlugin sets up the servers that are necessary for a DRA kubelet plugin. +func StartPlugin(logger klog.Logger, cdiDir, driverName string, nodeName string, fileOps FileOperations, opts ...kubeletplugin.Option) (*ExamplePlugin, error) { + if fileOps.Create == nil { + fileOps.Create = func(name string, content []byte) error { + return os.WriteFile(name, content, os.FileMode(0644)) + } + } + if fileOps.Remove == nil { + fileOps.Remove = func(name string) error { + if err := os.Remove(name); err != nil && !os.IsNotExist(err) { + return err + } + return nil + } + } + ex := &ExamplePlugin{ + logger: logger, + fileOps: fileOps, + cdiDir: cdiDir, + driverName: driverName, + nodeName: nodeName, + prepared: make(map[ClaimID]bool), + } + + opts = append(opts, + kubeletplugin.Logger(logger), + kubeletplugin.DriverName(driverName), + ) + d, err := kubeletplugin.Start(ex, opts...) + if err != nil { + return nil, fmt.Errorf("start kubelet plugin: %v", err) + } + ex.d = d + + return ex, nil +} + +// stop ensures that all servers are stopped and resources freed. +func (ex *ExamplePlugin) Stop() { + ex.d.Stop() +} + +func (ex *ExamplePlugin) IsRegistered() bool { + status := ex.d.RegistrationStatus() + if status == nil { + return false + } + return status.PluginRegistered +} + +// NodePrepareResource ensures that the CDI file for the claim exists. It uses +// a deterministic name to simplify NodeUnprepareResource (no need to remember +// or discover the name) and idempotency (when called again, the file simply +// gets written again). +func (ex *ExamplePlugin) NodePrepareResource(ctx context.Context, req *drapbv1.NodePrepareResourceRequest) (*drapbv1.NodePrepareResourceResponse, error) { + logger := klog.FromContext(ctx) + + // Determine environment variables. + var p parameters + if err := json.Unmarshal([]byte(req.ResourceHandle), &p); err != nil { + return nil, fmt.Errorf("unmarshal resource handle: %v", err) + } + + // Sanity check scheduling. + if p.NodeName != "" && ex.nodeName != "" && p.NodeName != ex.nodeName { + return nil, fmt.Errorf("claim was allocated for %q, cannot be prepared on %q", p.NodeName, ex.nodeName) + } + + // CDI wants env variables as set of strings. + envs := []string{} + for key, val := range p.EnvVars { + envs = append(envs, key+"="+val) + } + + deviceName := "claim-" + req.ClaimUid + vendor := ex.driverName + class := "test" + spec := &spec{ + Version: "0.2.0", // This has to be a version accepted by the runtimes. + Kind: vendor + "/" + class, + // At least one device is required and its entry must have more + // than just the name. + Devices: []device{ + { + Name: deviceName, + ContainerEdits: containerEdits{ + Env: envs, + }, + }, + }, + } + filePath := ex.getJSONFilePath(req.ClaimUid) + buffer, err := json.Marshal(spec) + if err != nil { + return nil, fmt.Errorf("marshal spec: %v", err) + } + if err := ex.fileOps.Create(filePath, buffer); err != nil { + return nil, fmt.Errorf("failed to write CDI file %v", err) + } + + dev := vendor + "/" + class + "=" + deviceName + resp := &drapbv1.NodePrepareResourceResponse{CdiDevices: []string{dev}} + + ex.mutex.Lock() + defer ex.mutex.Unlock() + ex.prepared[ClaimID{Name: req.ClaimName, UID: req.ClaimUid}] = true + + logger.V(3).Info("CDI file created", "path", filePath, "device", dev) + return resp, nil +} + +// NodeUnprepareResource removes the CDI file created by +// NodePrepareResource. It's idempotent, therefore it is not an error when that +// file is already gone. +func (ex *ExamplePlugin) NodeUnprepareResource(ctx context.Context, req *drapbv1.NodeUnprepareResourceRequest) (*drapbv1.NodeUnprepareResourceResponse, error) { + logger := klog.FromContext(ctx) + + filePath := ex.getJSONFilePath(req.ClaimUid) + if err := ex.fileOps.Remove(filePath); err != nil { + return nil, fmt.Errorf("error removing CDI file: %v", err) + } + logger.V(3).Info("CDI file removed", "path", filePath) + + ex.mutex.Lock() + defer ex.mutex.Unlock() + delete(ex.prepared, ClaimID{Name: req.ClaimName, UID: req.ClaimUid}) + + return &drapbv1.NodeUnprepareResourceResponse{}, nil +} + +func (ex *ExamplePlugin) GetPreparedResources() []ClaimID { + ex.mutex.Lock() + defer ex.mutex.Unlock() + var prepared []ClaimID + for claimID := range ex.prepared { + prepared = append(prepared, claimID) + } + return prepared +} diff --git a/test/e2e/dra/test-driver/app/server.go b/test/e2e/dra/test-driver/app/server.go new file mode 100644 index 00000000000..4be3ea34f32 --- /dev/null +++ b/test/e2e/dra/test-driver/app/server.go @@ -0,0 +1,319 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package app does all of the work necessary to configure and run a +// Kubernetes app process. +package app + +import ( + "context" + "encoding/json" + "fmt" + "net" + "net/http" + "net/http/pprof" + "os" + "os/signal" + "path" + "path/filepath" + "strings" + "syscall" + "time" + + "github.com/spf13/cobra" + "k8s.io/component-base/metrics" + + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + cliflag "k8s.io/component-base/cli/flag" + "k8s.io/component-base/featuregate" + "k8s.io/component-base/logs" + logsapi "k8s.io/component-base/logs/api/v1" + "k8s.io/component-base/metrics/legacyregistry" + "k8s.io/component-base/term" + "k8s.io/dynamic-resource-allocation/kubeletplugin" + "k8s.io/dynamic-resource-allocation/leaderelection" + "k8s.io/klog/v2" +) + +// NewCommand creates a *cobra.Command object with default parameters. +func NewCommand() *cobra.Command { + o := logsapi.NewLoggingConfiguration() + var clientset kubernetes.Interface + var config *rest.Config + ctx := context.Background() + logger := klog.Background() + + cmd := &cobra.Command{ + Use: "cdi-test-driver", + Long: "cdi-test-driver implements a resource driver controller and kubelet plugin.", + } + sharedFlagSets := cliflag.NamedFlagSets{} + fs := sharedFlagSets.FlagSet("logging") + logsapi.AddFlags(o, fs) + logs.AddFlags(fs, logs.SkipLoggingConfigurationFlags()) + + fs = sharedFlagSets.FlagSet("Kubernetes client") + kubeconfig := fs.String("kubeconfig", "", "Absolute path to the kube.config file. Either this or KUBECONFIG need to be set if the driver is being run out of cluster.") + kubeAPIQPS := fs.Float32("kube-api-qps", 5, "QPS to use while communicating with the kubernetes apiserver.") + kubeAPIBurst := fs.Int("kube-api-burst", 10, "Burst to use while communicating with the kubernetes apiserver.") + workers := fs.Int("workers", 10, "Concurrency to process multiple claims") + + fs = sharedFlagSets.FlagSet("http server") + httpEndpoint := fs.String("http-endpoint", "", + "The TCP network address where the HTTP server for diagnostics, including pprof, metrics and (if applicable) leader election health check, will listen (example: `:8080`). The default is the empty string, which means the server is disabled.") + metricsPath := fs.String("metrics-path", "/metrics", "The HTTP path where Prometheus metrics will be exposed, disabled if empty.") + profilePath := fs.String("pprof-path", "", "The HTTP path where pprof profiling will be available, disabled if empty.") + + fs = sharedFlagSets.FlagSet("CDI") + driverName := fs.String("drivername", "test-driver.cdi.k8s.io", "Resource driver name.") + + fs = sharedFlagSets.FlagSet("other") + featureGate := featuregate.NewFeatureGate() + utilruntime.Must(logsapi.AddFeatureGates(featureGate)) + featureGate.AddFlag(fs) + + fs = cmd.PersistentFlags() + for _, f := range sharedFlagSets.FlagSets { + fs.AddFlagSet(f) + } + + mux := http.NewServeMux() + + cmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { + // Activate logging as soon as possible, after that + // show flags with the final logging configuration. + + if err := logsapi.ValidateAndApply(o, featureGate); err != nil { + return err + } + + // get the KUBECONFIG from env if specified (useful for local/debug cluster) + kubeconfigEnv := os.Getenv("KUBECONFIG") + + if kubeconfigEnv != "" { + logger.Info("Found KUBECONFIG environment variable set, using that..") + *kubeconfig = kubeconfigEnv + } + + var err error + if *kubeconfig == "" { + config, err = rest.InClusterConfig() + if err != nil { + return fmt.Errorf("create in-cluster client configuration: %v", err) + } + } else { + config, err = clientcmd.BuildConfigFromFlags("", *kubeconfig) + if err != nil { + return fmt.Errorf("create out-of-cluster client configuration: %v", err) + } + } + config.QPS = *kubeAPIQPS + config.Burst = *kubeAPIBurst + + clientset, err = kubernetes.NewForConfig(config) + if err != nil { + return fmt.Errorf("create client: %v", err) + } + + if *httpEndpoint != "" { + if *metricsPath != "" { + // For workqueue and leader election metrics, set up via the anonymous imports of: + // https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/component-base/metrics/prometheus/workqueue/metrics.go + // https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/component-base/metrics/prometheus/clientgo/leaderelection/metrics.go + // + // Also to happens to include Go runtime and process metrics: + // https://github.com/kubernetes/kubernetes/blob/9780d88cb6a4b5b067256ecb4abf56892093ee87/staging/src/k8s.io/component-base/metrics/legacyregistry/registry.go#L46-L49 + gatherer := legacyregistry.DefaultGatherer + actualPath := path.Join("/", *metricsPath) + logger.Info("Starting metrics", "path", actualPath) + mux.Handle(actualPath, + metrics.HandlerFor(gatherer, metrics.HandlerOpts{})) + } + + if *profilePath != "" { + actualPath := path.Join("/", *profilePath) + logger.Info("Starting profiling", "path", actualPath) + mux.HandleFunc(path.Join("/", *profilePath), pprof.Index) + mux.HandleFunc(path.Join("/", *profilePath, "cmdline"), pprof.Cmdline) + mux.HandleFunc(path.Join("/", *profilePath, "profile"), pprof.Profile) + mux.HandleFunc(path.Join("/", *profilePath, "symbol"), pprof.Symbol) + mux.HandleFunc(path.Join("/", *profilePath, "trace"), pprof.Trace) + } + + listener, err := net.Listen("tcp", *httpEndpoint) + if err != nil { + return fmt.Errorf("listen on HTTP endpoint: %v", err) + } + + go func() { + logger.Info("Starting HTTP server", "endpoint", *httpEndpoint) + err := http.Serve(listener, mux) + if err != nil { + logger.Error(err, "HTTP server failed") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + }() + } + + return nil + } + + controller := &cobra.Command{ + Use: "controller", + Short: "run as resource controller", + Long: "cdi-test-driver controller runs as a resource driver controller.", + Args: cobra.ExactArgs(0), + } + controllerFlagSets := cliflag.NamedFlagSets{} + fs = controllerFlagSets.FlagSet("leader election") + enableLeaderElection := fs.Bool("leader-election", false, + "Enables leader election. If leader election is enabled, additional RBAC rules are required.") + leaderElectionNamespace := fs.String("leader-election-namespace", "", + "Namespace where the leader election resource lives. Defaults to the pod namespace if not set.") + leaderElectionLeaseDuration := fs.Duration("leader-election-lease-duration", 15*time.Second, + "Duration, in seconds, that non-leader candidates will wait to force acquire leadership.") + leaderElectionRenewDeadline := fs.Duration("leader-election-renew-deadline", 10*time.Second, + "Duration, in seconds, that the acting leader will retry refreshing leadership before giving up.") + leaderElectionRetryPeriod := fs.Duration("leader-election-retry-period", 5*time.Second, + "Duration, in seconds, the LeaderElector clients should wait between tries of actions.") + resourceConfig := fs.String("resource-config", "", "A JSON file containing a Resources struct. Defaults are unshared, network-attached resources.") + fs = controller.Flags() + for _, f := range controllerFlagSets.FlagSets { + fs.AddFlagSet(f) + } + + controller.RunE = func(cmd *cobra.Command, args []string) error { + resources := Resources{} + if *resourceConfig != "" { + file, err := os.Open(*resourceConfig) + if err != nil { + return fmt.Errorf("open resource config: %v", err) + } + decoder := json.NewDecoder(file) + decoder.DisallowUnknownFields() + if err := decoder.Decode(&resources); err != nil { + return fmt.Errorf("parse resource config %q: %v", *resourceConfig, err) + } + } + + run := func() { + controller := NewController(clientset, *driverName, resources) + controller.Run(ctx, *workers) + } + + if !*enableLeaderElection { + run() + return nil + } + + // This must not change between releases. + lockName := *driverName + + // Create a new clientset for leader election + // to avoid starving it when the normal traffic + // exceeds the QPS+burst limits. + leClientset, err := kubernetes.NewForConfig(config) + if err != nil { + return fmt.Errorf("create leaderelection client: %v", err) + } + + le := leaderelection.New(leClientset, lockName, + func(ctx context.Context) { + run() + }, + leaderelection.LeaseDuration(*leaderElectionLeaseDuration), + leaderelection.RenewDeadline(*leaderElectionRenewDeadline), + leaderelection.RetryPeriod(*leaderElectionRetryPeriod), + leaderelection.Namespace(*leaderElectionNamespace), + ) + if *httpEndpoint != "" { + le.PrepareHealthCheck(mux) + } + if err := le.Run(); err != nil { + return fmt.Errorf("leader election failed: %v", err) + } + + return nil + } + cmd.AddCommand(controller) + + kubeletPlugin := &cobra.Command{ + Use: "kubelet-plugin", + Short: "run as kubelet plugin", + Long: "cdi-test-driver kubelet-plugin runs as a device plugin for kubelet that supports dynamic resource allocation.", + Args: cobra.ExactArgs(0), + } + kubeletPluginFlagSets := cliflag.NamedFlagSets{} + fs = kubeletPluginFlagSets.FlagSet("kubelet") + pluginRegistrationPath := fs.String("plugin-registration-path", "/var/lib/kubelet/plugins_registry", "The directory where kubelet looks for plugin registration sockets, in the filesystem of the driver.") + endpoint := fs.String("endpoint", "/var/lib/kubelet/plugins/test-driver/dra.sock", "The Unix domain socket where the driver will listen for kubelet requests, in the filesystem of the driver.") + draAddress := fs.String("dra-address", "/var/lib/kubelet/plugins/test-driver/dra.sock", "The Unix domain socket that kubelet will connect to for dynamic resource allocation requests, in the filesystem of kubelet.") + fs = kubeletPluginFlagSets.FlagSet("CDI") + cdiDir := fs.String("cdi-dir", "/var/run/cdi", "directory for dynamically created CDI JSON files") + fs = kubeletPlugin.Flags() + for _, f := range kubeletPluginFlagSets.FlagSets { + fs.AddFlagSet(f) + } + kubeletPlugin.RunE = func(cmd *cobra.Command, args []string) error { + // Ensure that directories exist, creating them if necessary. We want + // to know early if there is a setup problem that would prevent + // creating those directories. + if err := os.MkdirAll(*cdiDir, os.FileMode(0750)); err != nil { + return fmt.Errorf("create CDI directory: %v", err) + } + if err := os.MkdirAll(filepath.Dir(*endpoint), 0750); err != nil { + return fmt.Errorf("create socket directory: %v", err) + } + + plugin, err := StartPlugin(logger, *cdiDir, *driverName, "", FileOperations{}, + kubeletplugin.PluginSocketPath(*endpoint), + kubeletplugin.RegistrarSocketPath(path.Join(*pluginRegistrationPath, *driverName+"-reg.sock")), + kubeletplugin.KubeletPluginSocketPath(*draAddress), + ) + if err != nil { + return fmt.Errorf("start example plugin: %v", err) + } + + // Handle graceful shutdown. We need to delete Unix domain + // sockets. + sigc := make(chan os.Signal, 1) + signal.Notify(sigc, os.Interrupt, syscall.SIGTERM) + logger.Info("Waiting for signal.") + sig := <-sigc + logger.Info("Received signal, shutting down.", "signal", sig) + plugin.Stop() + return nil + } + cmd.AddCommand(kubeletPlugin) + + // SetUsageAndHelpFunc takes care of flag grouping. However, + // it doesn't support listing child commands. We add those + // to cmd.Use. + cols, _, _ := term.TerminalSize(cmd.OutOrStdout()) + cliflag.SetUsageAndHelpFunc(cmd, sharedFlagSets, cols) + var children []string + for _, child := range cmd.Commands() { + children = append(children, child.Use) + } + cmd.Use += " [shared flags] " + strings.Join(children, "|") + cliflag.SetUsageAndHelpFunc(controller, controllerFlagSets, cols) + cliflag.SetUsageAndHelpFunc(kubeletPlugin, kubeletPluginFlagSets, cols) + + return cmd +} diff --git a/test/e2e/dra/test-driver/deploy/example/broken-resourceclass.yaml b/test/e2e/dra/test-driver/deploy/example/broken-resourceclass.yaml new file mode 100644 index 00000000000..f4ecb6f2eb0 --- /dev/null +++ b/test/e2e/dra/test-driver/deploy/example/broken-resourceclass.yaml @@ -0,0 +1,14 @@ +# This storage class intentionally doesn't match any nodes. +# When using it instead of a functional one, scheduling a pod leads to: +# Warning FailedScheduling 16s default-scheduler 0/1 nodes are available: 1 excluded via potential node filter in resource class. + +apiVersion: resource.k8s.io/v1alpha1 +kind: ResourceClass +metadata: + name: example +driverName: test-driver.cdi.k8s.io +suitableNodes: + nodeSelectorTerms: + - matchExpressions: + - key: no-such-label + operator: Exists diff --git a/test/e2e/dra/test-driver/deploy/example/pod-external.yaml b/test/e2e/dra/test-driver/deploy/example/pod-external.yaml new file mode 100644 index 00000000000..4aea64fd0df --- /dev/null +++ b/test/e2e/dra/test-driver/deploy/example/pod-external.yaml @@ -0,0 +1,40 @@ +# One external resource claim, one pod, two containers. +# One container uses resource, one does not. +apiVersion: v1 +kind: ConfigMap +metadata: + name: external-claim-parameters + namespace: default +data: + a: b +--- +apiVersion: resource.k8s.io/v1alpha1 +kind: ResourceClaim +metadata: + name: external-claim +spec: + resourceClassName: example + parametersRef: + kind: ConfigMap + name: external-claim-parameters +--- +apiVersion: v1 +kind: Pod +metadata: + name: test-external-claim +spec: + restartPolicy: Never + containers: + - name: with-resource + image: registry.k8s.io/e2e-test-images/busybox:1.29-2 + command: ["sh", "-c", "set && mount && ls -la /dev/"] + resources: + claims: + - resource + - name: without-resource + image: registry.k8s.io/e2e-test-images/busybox:1.29-2 + command: ["sh", "-c", "set && mount && ls -la /dev/"] + resourceClaims: + - name: resource + source: + resourceClaimName: external-claim diff --git a/test/e2e/dra/test-driver/deploy/example/pod-inline-multiple.yaml b/test/e2e/dra/test-driver/deploy/example/pod-inline-multiple.yaml new file mode 100644 index 00000000000..3a49c9a7de0 --- /dev/null +++ b/test/e2e/dra/test-driver/deploy/example/pod-inline-multiple.yaml @@ -0,0 +1,48 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: pause-claim-parameters + namespace: default +data: + a: b +--- +apiVersion: resource.k8s.io/v1alpha1 +kind: ResourceClaimTemplate +metadata: + name: pause-template + namespace: default +spec: + metadata: + labels: + app: inline-resource + spec: + resourceClassName: example + parametersRef: + kind: ConfigMap + name: pause-claim-parameters +--- +apiVersion: v1 +kind: Pod +metadata: + name: pause + labels: + name: pause +spec: + containers: + - name: pause1 + image: "k8s.gcr.io/pause:3.6" + resources: + claims: + - name: resource1 + - name: pause2 + image: "k8s.gcr.io/pause:3.6" + resources: + claims: + - name: resource2 + resourceClaims: + - name: resource1 + source: + resourceClaimTemplateName: pause-template + - name: resource2 + source: + resourceClaimTemplateName: pause-template diff --git a/test/e2e/dra/test-driver/deploy/example/pod-inline.yaml b/test/e2e/dra/test-driver/deploy/example/pod-inline.yaml new file mode 100644 index 00000000000..d1145e3dae6 --- /dev/null +++ b/test/e2e/dra/test-driver/deploy/example/pod-inline.yaml @@ -0,0 +1,45 @@ +# One inline resource claim, one pod, two containers. +# One container uses resource, one does not. +apiVersion: v1 +kind: ConfigMap +metadata: + name: inline-claim-parameters + namespace: default +data: + a: b +--- +apiVersion: resource.k8s.io/v1alpha1 +kind: ResourceClaimTemplate +metadata: + name: test-inline-claim-template + namespace: default +spec: + metadata: + labels: + app: inline-resource + spec: + resourceClassName: example + parametersRef: + kind: ConfigMap + name: pause-claim-parameters +--- +apiVersion: v1 +kind: Pod +metadata: + name: test-inline-claim +spec: + restartPolicy: Never + containers: + - name: with-resource + image: registry.k8s.io/e2e-test-images/busybox:1.29-2 + command: ["sh", "-c", "set && mount && ls -la /dev/"] + resources: + claims: + - name: resource + - name: without-resource + image: registry.k8s.io/e2e-test-images/busybox:1.29-2 + command: ["sh", "-c", "set && mount && ls -la /dev/"] + resourceClaims: + - name: resource + source: + resourceClaimTemplateName: test-inline-claim-template diff --git a/test/e2e/dra/test-driver/deploy/example/pod-shared.yaml b/test/e2e/dra/test-driver/deploy/example/pod-shared.yaml new file mode 100644 index 00000000000..b32a0e40381 --- /dev/null +++ b/test/e2e/dra/test-driver/deploy/example/pod-shared.yaml @@ -0,0 +1,61 @@ +# One external resource claim, two pods, two containers in each pod. +# Pods share the same resource. +# One container uses resource, one does not. +apiVersion: v1 +kind: ConfigMap +metadata: + name: shared-claim-parameters +data: + a: b +--- +apiVersion: resource.k8s.io/v1alpha1 +kind: ResourceClaim +metadata: + name: shared-claim +spec: + resourceClassName: example + parametersRef: + kind: ConfigMap + name: shared-claim-parameters +--- +apiVersion: v1 +kind: Pod +metadata: + name: test-shared-claim +spec: + restartPolicy: Never + containers: + - name: with-resource + image: registry.k8s.io/e2e-test-images/busybox:1.29-2 + command: ["sh", "-c", "set && mount && ls -la /dev/"] + resources: + claims: + - name: resource + - name: without-resource + image: registry.k8s.io/e2e-test-images/busybox:1.29-2 + command: ["sh", "-c", "set && mount && ls -la /dev/"] + resourceClaims: + - name: resource + source: + resourceClaimName: shared-claim +--- +apiVersion: v1 +kind: Pod +metadata: + name: test-shared-claim-2 +spec: + restartPolicy: Never + containers: + - name: with-resource + image: registry.k8s.io/e2e-test-images/busybox:1.29-2 + command: ["sh", "-c", "set && mount && ls -la /dev/"] + resources: + claims: + - name: resource + - name: without-resource + image: registry.k8s.io/e2e-test-images/busybox:1.29-2 + command: ["sh", "-c", "set && mount && ls -la /dev/"] + resourceClaims: + - name: resource + source: + resourceClaimName: shared-claim diff --git a/test/e2e/dra/test-driver/deploy/example/resourceclaim.yaml b/test/e2e/dra/test-driver/deploy/example/resourceclaim.yaml new file mode 100644 index 00000000000..ce37440738d --- /dev/null +++ b/test/e2e/dra/test-driver/deploy/example/resourceclaim.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: example-claim-parameters + namespace: default +data: + a: b +--- +apiVersion: resource.k8s.io/v1alpha1 +kind: ResourceClaim +metadata: + name: example + namespace: default +spec: + allocationMode: Immediate + resourceClassName: example + parametersRef: + kind: ConfigMap + name: example-claim-parameters diff --git a/test/e2e/dra/test-driver/deploy/example/resourceclass.yaml b/test/e2e/dra/test-driver/deploy/example/resourceclass.yaml new file mode 100644 index 00000000000..42d5c2c9689 --- /dev/null +++ b/test/e2e/dra/test-driver/deploy/example/resourceclass.yaml @@ -0,0 +1,7 @@ +apiVersion: resource.k8s.io/v1alpha1 +kind: ResourceClass +metadata: + name: example +driverName: test-driver.cdi.k8s.io +# TODO: +# parameters diff --git a/test/e2e/dra/test-driver/dra-test-driver.go b/test/e2e/dra/test-driver/dra-test-driver.go new file mode 100644 index 00000000000..ad93cc84b1c --- /dev/null +++ b/test/e2e/dra/test-driver/dra-test-driver.go @@ -0,0 +1,35 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "os" + + "k8s.io/component-base/cli" + _ "k8s.io/component-base/logs/json/register" // for JSON log output support + _ "k8s.io/component-base/metrics/prometheus/clientgo/leaderelection" // register leader election in the default legacy registry + _ "k8s.io/component-base/metrics/prometheus/restclient" // for client metric registration + _ "k8s.io/component-base/metrics/prometheus/version" // for version metric registration + _ "k8s.io/component-base/metrics/prometheus/workqueue" // register work queues in the default legacy registry + "k8s.io/kubernetes/test/e2e/dra/test-driver/app" +) + +func main() { + command := app.NewCommand() + code := cli.Run(command) + os.Exit(code) +} diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 93032c185b0..1b124cc831f 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -52,6 +52,7 @@ import ( _ "k8s.io/kubernetes/test/e2e/autoscaling" _ "k8s.io/kubernetes/test/e2e/cloud" _ "k8s.io/kubernetes/test/e2e/common" + _ "k8s.io/kubernetes/test/e2e/dra" _ "k8s.io/kubernetes/test/e2e/instrumentation" _ "k8s.io/kubernetes/test/e2e/kubectl" _ "k8s.io/kubernetes/test/e2e/lifecycle" diff --git a/test/e2e/framework/pod/wait_test.go b/test/e2e/framework/pod/wait_test.go index 3cae475458d..f3d28b3ef73 100644 --- a/test/e2e/framework/pod/wait_test.go +++ b/test/e2e/framework/pod/wait_test.go @@ -185,6 +185,7 @@ INFO: Unexpected error: wait for pod pending-pod running: OS: nil, HostUsers: nil, SchedulingGates: nil, + ResourceClaims: nil, }, Status: { Phase: "", diff --git a/test/e2e/testing-manifests/dra/OWNERS b/test/e2e/testing-manifests/dra/OWNERS new file mode 100644 index 00000000000..03cc9aff5b4 --- /dev/null +++ b/test/e2e/testing-manifests/dra/OWNERS @@ -0,0 +1,11 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - klueska + - pohly +reviewers: + - klueska + - pohly + - bart0sh +labels: + - sig/node diff --git a/test/e2e/testing-manifests/dra/dra-test-driver-proxy.yaml b/test/e2e/testing-manifests/dra/dra-test-driver-proxy.yaml new file mode 100644 index 00000000000..377bb2e587b --- /dev/null +++ b/test/e2e/testing-manifests/dra/dra-test-driver-proxy.yaml @@ -0,0 +1,85 @@ +# This YAML file deploys the csi-driver-host-path on a number of nodes such +# that it proxies all connections from kubelet (plugin registration and dynamic +# resource allocation). The actual handling of those connections then happens +# inside the e2e.test binary via test/e2e/storage/drivers/proxy. This approach +# has the advantage that no separate container image with the test driver is +# needed and that tests have full control over the driver, for example for +# error injection. +# +# The csi-driver-host-path image is used because: +# - it has the necessary proxy mode (https://github.com/kubernetes-csi/csi-driver-host-path/commit/65480fc74d550a9a5aa81e850955cc20403857b1) +# - its base image contains a shell (useful for creating files) +# - the image is already a dependency of e2e.test + +kind: ReplicaSet +apiVersion: apps/v1 +metadata: + name: dra-test-driver + labels: + app.kubernetes.io/instance: test-driver.dra.k8s.io + app.kubernetes.io/part-of: dra-test-driver + app.kubernetes.io/name: dra-test-driver-kubelet-plugin + app.kubernetes.io/component: kubelet-plugin +spec: + selector: + matchLabels: + app.kubernetes.io/instance: test-driver.dra.k8s.io + app.kubernetes.io/part-of: dra-test-driver + app.kubernetes.io/name: dra-test-driver-kubelet-plugin + app.kubernetes.io/component: kubelet-plugin + replicas: 1 + template: + metadata: + labels: + app.kubernetes.io/instance: test-driver.dra.k8s.io + app.kubernetes.io/part-of: dra-test-driver + app.kubernetes.io/name: dra-test-driver-kubelet-plugin + app.kubernetes.io/component: kubelet-plugin + spec: + # Ensure that all pods run on distinct nodes. + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/instance: test-driver.dra.k8s.io + topologyKey: kubernetes.io/hostname + + containers: + - name: registrar + image: registry.k8s.io/sig-storage/hostpathplugin:v1.7.3 + args: + - "--v=5" + - "--endpoint=/plugins_registry/dra-test-driver-reg.sock" + - "--proxy-endpoint=tcp://:9000" + volumeMounts: + - mountPath: /plugins_registry + name: registration-dir + + - name: plugin + image: registry.k8s.io/sig-storage/hostpathplugin:v1.7.3 + args: + - "--v=5" + - "--endpoint=/dra/dra-test-driver.sock" + - "--proxy-endpoint=tcp://:9001" + securityContext: + privileged: true + volumeMounts: + - mountPath: /dra + name: socket-dir + - mountPath: /cdi + name: cdi-dir + + volumes: + - hostPath: + path: /var/lib/kubelet/plugins + type: DirectoryOrCreate + name: socket-dir + - hostPath: + path: /var/run/cdi + type: DirectoryOrCreate + name: cdi-dir + - hostPath: + path: /var/lib/kubelet/plugins_registry + type: DirectoryOrCreate + name: registration-dir diff --git a/test/integration/apiserver/apply/reset_fields_test.go b/test/integration/apiserver/apply/reset_fields_test.go index 20a25188af4..ff4f6d696c9 100644 --- a/test/integration/apiserver/apply/reset_fields_test.go +++ b/test/integration/apiserver/apply/reset_fields_test.go @@ -64,6 +64,8 @@ var resetFieldsStatusData = map[schema.GroupVersionResource]string{ gvr("storage.k8s.io", "v1", "volumeattachments"): `{"status": {"attached": false}}`, gvr("policy", "v1", "poddisruptionbudgets"): `{"status": {"currentHealthy": 25}}`, gvr("policy", "v1beta1", "poddisruptionbudgets"): `{"status": {"currentHealthy": 25}}`, + gvr("resource.k8s.io", "v1alpha1", "podschedulings"): `{"status": {"resourceClaims": [{"name": "my-claim", "unsuitableNodes": ["node2"]}]}}`, // Not really a conflict with status_test.go: Apply just stores both nodes. Conflict testing therefore gets disabled for podschedulings. + gvr("resource.k8s.io", "v1alpha1", "resourceclaims"): `{"status": {"driverName": "other.example.com"}}`, gvr("internal.apiserver.k8s.io", "v1alpha1", "storageversions"): `{"status": {"commonEncodingVersion":"v1","storageVersions":[{"apiServerID":"1","decodableVersions":["v1","v2"],"encodingVersion":"v1"}],"conditions":[{"type":"AllEncodingVersionsEqual","status":"False","lastTransitionTime":"2020-01-01T00:00:00Z","reason":"allEncodingVersionsEqual","message":"all encoding versions are set to v1"}]}}`, } @@ -84,6 +86,10 @@ var noConflicts = map[string]struct{}{ // namespaces only have a spec.finalizers field which is also skipped, // thus it will never have a conflict. "namespaces": {}, + // podschedulings.status only has a list which contains items with a list, + // therefore apply works because it simply merges either the outer or + // the inner list. + "podschedulings": {}, } var image2 = image.GetE2EImage(image.Etcd) @@ -140,6 +146,10 @@ var resetFieldsSpecData = map[schema.GroupVersionResource]string{ gvr("awesome.bears.com", "v3", "pandas"): `{"spec": {"replicas": 302}}`, gvr("apiregistration.k8s.io", "v1beta1", "apiservices"): `{"metadata": {"labels": {"a":"c"}}, "spec": {"group": "foo2.com"}}`, gvr("apiregistration.k8s.io", "v1", "apiservices"): `{"metadata": {"labels": {"a":"c"}}, "spec": {"group": "foo2.com"}}`, + gvr("resource.k8s.io", "v1alpha1", "podschedulings"): `{"spec": {"selectedNode": "node2name"}}`, + gvr("resource.k8s.io", "v1alpha1", "resourceclasses"): `{"driverName": "other.example.com"}`, + gvr("resource.k8s.io", "v1alpha1", "resourceclaims"): `{"spec": {"resourceClassName": "class2name"}}`, // ResourceClassName is immutable, but that doesn't matter for the test. + gvr("resource.k8s.io", "v1alpha1", "resourceclaimtemplates"): `{"spec": {"spec": {"resourceClassName": "class2name"}}}`, gvr("internal.apiserver.k8s.io", "v1alpha1", "storageversions"): `{}`, } diff --git a/test/integration/apiserver/apply/status_test.go b/test/integration/apiserver/apply/status_test.go index 8aca1c8ea51..8d4593f14d7 100644 --- a/test/integration/apiserver/apply/status_test.go +++ b/test/integration/apiserver/apply/status_test.go @@ -54,6 +54,8 @@ var statusData = map[schema.GroupVersionResource]string{ gvr("storage.k8s.io", "v1", "volumeattachments"): `{"status": {"attached": true}}`, gvr("policy", "v1", "poddisruptionbudgets"): `{"status": {"currentHealthy": 5}}`, gvr("policy", "v1beta1", "poddisruptionbudgets"): `{"status": {"currentHealthy": 5}}`, + gvr("resource.k8s.io", "v1alpha1", "podschedulings"): `{"status": {"resourceClaims": [{"name": "my-claim", "unsuitableNodes": ["node1"]}]}}`, + gvr("resource.k8s.io", "v1alpha1", "resourceclaims"): `{"status": {"driverName": "example.com"}}`, gvr("internal.apiserver.k8s.io", "v1alpha1", "storageversions"): `{"status": {"commonEncodingVersion":"v1","storageVersions":[{"apiServerID":"1","decodableVersions":["v1","v2"],"encodingVersion":"v1"}],"conditions":[{"type":"AllEncodingVersionsEqual","status":"True","lastTransitionTime":"2020-01-01T00:00:00Z","reason":"allEncodingVersionsEqual","message":"all encoding versions are set to v1"}]}}`, } diff --git a/test/integration/etcd/data.go b/test/integration/etcd/data.go index 8177c2479e7..2ac3c88f5d4 100644 --- a/test/integration/etcd/data.go +++ b/test/integration/etcd/data.go @@ -459,6 +459,25 @@ func GetEtcdStorageDataForNamespace(namespace string) map[schema.GroupVersionRes }, // -- + // k8s.io/kubernetes/pkg/apis/resource/v1alpha1 + gvr("resource.k8s.io", "v1alpha1", "resourceclasses"): { + Stub: `{"metadata": {"name": "class1name"}, "driverName": "example.com"}`, + ExpectedEtcdPath: "/registry/resourceclasses/class1name", + }, + gvr("resource.k8s.io", "v1alpha1", "resourceclaims"): { + Stub: `{"metadata": {"name": "claim1name"}, "spec": {"resourceClassName": "class1name", "allocationMode": "WaitForFirstConsumer"}}`, + ExpectedEtcdPath: "/registry/resourceclaims/" + namespace + "/claim1name", + }, + gvr("resource.k8s.io", "v1alpha1", "resourceclaimtemplates"): { + Stub: `{"metadata": {"name": "claimtemplate1name"}, "spec": {"spec": {"resourceClassName": "class1name", "allocationMode": "WaitForFirstConsumer"}}}`, + ExpectedEtcdPath: "/registry/resourceclaimtemplates/" + namespace + "/claimtemplate1name", + }, + gvr("resource.k8s.io", "v1alpha1", "podschedulings"): { + Stub: `{"metadata": {"name": "pod1name"}, "spec": {"selectedNode": "node1name", "potentialNodes": ["node1name", "node2name"]}}`, + ExpectedEtcdPath: "/registry/podschedulings/" + namespace + "/pod1name", + }, + // -- + // k8s.io/apiserver/pkg/apis/apiserverinternal/v1alpha1 gvr("internal.apiserver.k8s.io", "v1alpha1", "storageversions"): { Stub: `{"metadata":{"name":"sv1.test"},"spec":{}}`, diff --git a/test/integration/logs/benchmark/load_test.go b/test/integration/logs/benchmark/load_test.go index 7ac71096df8..3d250c845dd 100644 --- a/test/integration/logs/benchmark/load_test.go +++ b/test/integration/logs/benchmark/load_test.go @@ -152,7 +152,7 @@ if [ $count -eq 2 ]; then exit 0 fi while true; do sleep 1; done -],Args:[],WorkingDir:,Ports:[]ContainerPort{},Env:[]EnvVar{},Resources:ResourceRequirements{Limits:ResourceList{},Requests:ResourceList{},},VolumeMounts:[]VolumeMount{},LivenessProbe:nil,ReadinessProbe:nil,Lifecycle:nil,TerminationMessagePath:/dev/termination-log,ImagePullPolicy:,SecurityContext:nil,Stdin:false,StdinOnce:false,TTY:false,EnvFrom:[]EnvFromSource{},TerminationMessagePolicy:,VolumeDevices:[]VolumeDevice{},StartupProbe:nil,}] +],Args:[],WorkingDir:,Ports:[]ContainerPort{},Env:[]EnvVar{},Resources:ResourceRequirements{Limits:ResourceList{},Requests:ResourceList{},Claims:[]ResourceClaim{},},VolumeMounts:[]VolumeMount{},LivenessProbe:nil,ReadinessProbe:nil,Lifecycle:nil,TerminationMessagePath:/dev/termination-log,ImagePullPolicy:,SecurityContext:nil,Stdin:false,StdinOnce:false,TTY:false,EnvFrom:[]EnvFromSource{},TerminationMessagePolicy:,VolumeDevices:[]VolumeDevice{},StartupProbe:nil,}] `, structured: `"Creating container in pod" container=< &Container{Name:terminate-cmd-rpn,Image:registry.k8s.io/e2e-test-images/busybox:1.29-2,Command:[sh -c @@ -165,13 +165,13 @@ while true; do sleep 1; done exit 0 fi while true; do sleep 1; done - ],Args:[],WorkingDir:,Ports:[]ContainerPort{},Env:[]EnvVar{},Resources:ResourceRequirements{Limits:ResourceList{},Requests:ResourceList{},},VolumeMounts:[]VolumeMount{},LivenessProbe:nil,ReadinessProbe:nil,Lifecycle:nil,TerminationMessagePath:/dev/termination-log,ImagePullPolicy:,SecurityContext:nil,Stdin:false,StdinOnce:false,TTY:false,EnvFrom:[]EnvFromSource{},TerminationMessagePolicy:,VolumeDevices:[]VolumeDevice{},StartupProbe:nil,} + ],Args:[],WorkingDir:,Ports:[]ContainerPort{},Env:[]EnvVar{},Resources:ResourceRequirements{Limits:ResourceList{},Requests:ResourceList{},Claims:[]ResourceClaim{},},VolumeMounts:[]VolumeMount{},LivenessProbe:nil,ReadinessProbe:nil,Lifecycle:nil,TerminationMessagePath:/dev/termination-log,ImagePullPolicy:,SecurityContext:nil,Stdin:false,StdinOnce:false,TTY:false,EnvFrom:[]EnvFromSource{},TerminationMessagePolicy:,VolumeDevices:[]VolumeDevice{},StartupProbe:nil,} > `, // This is what the output would look like with JSON object. Because of https://github.com/kubernetes/kubernetes/issues/106652 we get the string instead. // json: `{"msg":"Creating container in pod","v":0,"container":{"name":"terminate-cmd-rpn","image":"registry.k8s.io/e2e-test-images/busybox:1.29-2","command":["sh -c \nf=/restart-count/restartCount\ncount=$(echo 'hello' >> $f ; wc -l $f | awk {'print $1'})\nif [ $count -eq 1 ]; then\n\texit 1\nfi\nif [ $count -eq 2 ]; then\n\texit 0\nfi\nwhile true; do sleep 1; done\n"],"resources":{},"terminationMessagePath":"/dev/termination-log"}} // `, - json: `{"msg":"Creating container in pod","v":0,"container":"&Container{Name:terminate-cmd-rpn,Image:registry.k8s.io/e2e-test-images/busybox:1.29-2,Command:[sh -c \nf=/restart-count/restartCount\ncount=$(echo 'hello' >> $f ; wc -l $f | awk {'print $1'})\nif [ $count -eq 1 ]; then\n\texit 1\nfi\nif [ $count -eq 2 ]; then\n\texit 0\nfi\nwhile true; do sleep 1; done\n],Args:[],WorkingDir:,Ports:[]ContainerPort{},Env:[]EnvVar{},Resources:ResourceRequirements{Limits:ResourceList{},Requests:ResourceList{},},VolumeMounts:[]VolumeMount{},LivenessProbe:nil,ReadinessProbe:nil,Lifecycle:nil,TerminationMessagePath:/dev/termination-log,ImagePullPolicy:,SecurityContext:nil,Stdin:false,StdinOnce:false,TTY:false,EnvFrom:[]EnvFromSource{},TerminationMessagePolicy:,VolumeDevices:[]VolumeDevice{},StartupProbe:nil,}"} + json: `{"msg":"Creating container in pod","v":0,"container":"&Container{Name:terminate-cmd-rpn,Image:registry.k8s.io/e2e-test-images/busybox:1.29-2,Command:[sh -c \nf=/restart-count/restartCount\ncount=$(echo 'hello' >> $f ; wc -l $f | awk {'print $1'})\nif [ $count -eq 1 ]; then\n\texit 1\nfi\nif [ $count -eq 2 ]; then\n\texit 0\nfi\nwhile true; do sleep 1; done\n],Args:[],WorkingDir:,Ports:[]ContainerPort{},Env:[]EnvVar{},Resources:ResourceRequirements{Limits:ResourceList{},Requests:ResourceList{},Claims:[]ResourceClaim{},},VolumeMounts:[]VolumeMount{},LivenessProbe:nil,ReadinessProbe:nil,Lifecycle:nil,TerminationMessagePath:/dev/termination-log,ImagePullPolicy:,SecurityContext:nil,Stdin:false,StdinOnce:false,TTY:false,EnvFrom:[]EnvFromSource{},TerminationMessagePolicy:,VolumeDevices:[]VolumeDevice{},StartupProbe:nil,}"} `, stats: logStats{ TotalLines: 2, diff --git a/vendor/k8s.io/dynamic-resource-allocation b/vendor/k8s.io/dynamic-resource-allocation new file mode 120000 index 00000000000..2aef427aa71 --- /dev/null +++ b/vendor/k8s.io/dynamic-resource-allocation @@ -0,0 +1 @@ +../../staging/src/k8s.io/dynamic-resource-allocation \ No newline at end of file diff --git a/vendor/modules.txt b/vendor/modules.txt index 908aef11871..4a732e228d6 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1305,6 +1305,7 @@ k8s.io/api/policy/v1beta1 k8s.io/api/rbac/v1 k8s.io/api/rbac/v1alpha1 k8s.io/api/rbac/v1beta1 +k8s.io/api/resource/v1alpha1 k8s.io/api/scheduling/v1 k8s.io/api/scheduling/v1alpha1 k8s.io/api/scheduling/v1beta1 @@ -1642,6 +1643,7 @@ k8s.io/client-go/applyconfigurations/policy/v1beta1 k8s.io/client-go/applyconfigurations/rbac/v1 k8s.io/client-go/applyconfigurations/rbac/v1alpha1 k8s.io/client-go/applyconfigurations/rbac/v1beta1 +k8s.io/client-go/applyconfigurations/resource/v1alpha1 k8s.io/client-go/applyconfigurations/scheduling/v1 k8s.io/client-go/applyconfigurations/scheduling/v1alpha1 k8s.io/client-go/applyconfigurations/scheduling/v1beta1 @@ -1713,6 +1715,8 @@ k8s.io/client-go/informers/rbac k8s.io/client-go/informers/rbac/v1 k8s.io/client-go/informers/rbac/v1alpha1 k8s.io/client-go/informers/rbac/v1beta1 +k8s.io/client-go/informers/resource +k8s.io/client-go/informers/resource/v1alpha1 k8s.io/client-go/informers/scheduling k8s.io/client-go/informers/scheduling/v1 k8s.io/client-go/informers/scheduling/v1alpha1 @@ -1810,6 +1814,8 @@ k8s.io/client-go/kubernetes/typed/rbac/v1alpha1 k8s.io/client-go/kubernetes/typed/rbac/v1alpha1/fake k8s.io/client-go/kubernetes/typed/rbac/v1beta1 k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake +k8s.io/client-go/kubernetes/typed/resource/v1alpha1 +k8s.io/client-go/kubernetes/typed/resource/v1alpha1/fake k8s.io/client-go/kubernetes/typed/scheduling/v1 k8s.io/client-go/kubernetes/typed/scheduling/v1/fake k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1 @@ -1860,6 +1866,7 @@ k8s.io/client-go/listers/policy/v1beta1 k8s.io/client-go/listers/rbac/v1 k8s.io/client-go/listers/rbac/v1alpha1 k8s.io/client-go/listers/rbac/v1beta1 +k8s.io/client-go/listers/resource/v1alpha1 k8s.io/client-go/listers/scheduling/v1 k8s.io/client-go/listers/scheduling/v1alpha1 k8s.io/client-go/listers/scheduling/v1beta1 @@ -2046,6 +2053,12 @@ k8s.io/cri-api/pkg/errors ## explicit; go 1.19 k8s.io/csi-translation-lib k8s.io/csi-translation-lib/plugins +# k8s.io/dynamic-resource-allocation v0.0.0 => ./staging/src/k8s.io/dynamic-resource-allocation +## explicit; go 1.19 +k8s.io/dynamic-resource-allocation/controller +k8s.io/dynamic-resource-allocation/kubeletplugin +k8s.io/dynamic-resource-allocation/leaderelection +k8s.io/dynamic-resource-allocation/resourceclaim # k8s.io/gengo v0.0.0-20220902162205-c0856e24416d ## explicit; go 1.13 k8s.io/gengo/args @@ -2245,6 +2258,7 @@ k8s.io/kubelet/pkg/apis/credentialprovider/v1 k8s.io/kubelet/pkg/apis/credentialprovider/v1alpha1 k8s.io/kubelet/pkg/apis/credentialprovider/v1beta1 k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1 +k8s.io/kubelet/pkg/apis/dra/v1alpha1 k8s.io/kubelet/pkg/apis/pluginregistration/v1 k8s.io/kubelet/pkg/apis/podresources/v1 k8s.io/kubelet/pkg/apis/podresources/v1alpha1 @@ -2502,6 +2516,7 @@ sigs.k8s.io/yaml # k8s.io/controller-manager => ./staging/src/k8s.io/controller-manager # k8s.io/cri-api => ./staging/src/k8s.io/cri-api # k8s.io/csi-translation-lib => ./staging/src/k8s.io/csi-translation-lib +# k8s.io/dynamic-resource-allocation => ./staging/src/k8s.io/dynamic-resource-allocation # k8s.io/kms => ./staging/src/k8s.io/kms # k8s.io/kube-aggregator => ./staging/src/k8s.io/kube-aggregator # k8s.io/kube-controller-manager => ./staging/src/k8s.io/kube-controller-manager