diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 31aafb98f2..d3c69a9434 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -214,6 +214,9 @@ "io.k8s.api.autoscaling.v2.HorizontalPodAutoscaler": { "description": "HorizontalPodAutoscaler is the configuration for a horizontal pod autoscaler, which automatically manages the replica count of any resource implementing the scale subresource based on the metrics specified.", "type": "object", + "required": [ + "spec" + ], "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", @@ -838,6 +841,9 @@ "io.k8s.api.batch.v1.CronJob": { "description": "CronJob represents the configuration of a single cron job.", "type": "object", + "required": [ + "spec" + ], "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", @@ -4778,6 +4784,19 @@ } } }, + "io.k8s.api.core.v1.ImageVolumeStatus": { + "description": "ImageVolumeStatus represents the image-based volume status.", + "type": "object", + "required": [ + "imageRef" + ], + "properties": { + "imageRef": { + "description": "ImageRef is the digest of the image used for this volume. It should have a value that's similar to the pod's status.containerStatuses[i].imageID. The ImageRef length should not exceed 256 characters.", + "type": "string" + } + } + }, "io.k8s.api.core.v1.KeyToPath": { "description": "Maps a string key to a path within a volume.", "type": "object", @@ -5516,6 +5535,37 @@ } } }, + "io.k8s.api.core.v1.NodeAllocatableResourceClaimStatus": { + "description": "NodeAllocatableResourceClaimStatus describes the status of node allocatable resources allocated via DRA.", + "type": "object", + "required": [ + "resourceClaimName", + "resources" + ], + "properties": { + "containers": { + "description": "Containers lists the names of all containers in this pod that reference the claim.", + "type": "array", + "items": { + "type": "string", + "default": "" + }, + "x-kubernetes-list-type": "set" + }, + "resourceClaimName": { + "description": "ResourceClaimName is the resource claim referenced by the pod that resulted in this node allocatable resource allocation.", + "type": "string", + "default": "" + }, + "resources": { + "description": "Resources is a map of the node-allocatable resource name to the aggregate quantity allocated to the claim.", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.api.resource.Quantity" + } + } + } + }, "io.k8s.api.core.v1.NodeCondition": { "description": "NodeCondition contains condition information for a node.", "type": "object", @@ -6708,7 +6758,7 @@ ] }, "portworxVolume": { - "description": "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on.", + "description": "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver.", "allOf": [ { "$ref": "#/components/schemas/io.k8s.api.core.v1.PortworxVolumeSource" @@ -6947,7 +6997,7 @@ ] }, "portworxVolume": { - "description": "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on.", + "description": "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver.", "allOf": [ { "$ref": "#/components/schemas/io.k8s.api.core.v1.PortworxVolumeSource" @@ -7331,7 +7381,7 @@ "type": "string" }, "observedGeneration": { - "description": "If set, this represents the .metadata.generation that the pod condition was set based upon. The PodObservedGenerationTracking feature gate must be enabled to use this field.", + "description": "If set, this represents the .metadata.generation that the pod condition was set based upon.", "type": "integer", "format": "int64" }, @@ -7660,7 +7710,7 @@ } }, "io.k8s.api.core.v1.PodResourceClaim": { - "description": "PodResourceClaim references exactly one ResourceClaim, either directly or by naming a ResourceClaimTemplate which is then turned into a ResourceClaim for the pod.\n\nIt 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.", + "description": "PodResourceClaim references exactly one ResourceClaim, either directly or by naming a ResourceClaimTemplate which is then turned into a ResourceClaim for the pod.\n\nIt 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.\n\nWhen the DRAWorkloadResourceClaims feature gate is enabled and this Pod belongs to a PodGroup, a PodResourceClaim is matched to a PodGroupResourceClaim if all of their fields are equal (Name, ResourceClaimName, and ResourceClaimTemplateName). A matched claim references a single ResourceClaim shared across all Pods in the PodGroup, reserved for the PodGroup in ResourceClaimStatus.ReservedFor rather than for individual Pods.", "type": "object", "required": [ "name" @@ -7676,7 +7726,7 @@ "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 pod name and resource name, along with a generated component, will be used to form a unique name for the ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses.\n\nThis field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim.\n\nExactly one of ResourceClaimName and ResourceClaimTemplateName must be set.", + "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 pod name and resource name, along with a generated component, will be used to form a unique name for the ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses.\n\nWhen the DRAWorkloadResourceClaims feature gate is enabled and the pod belongs to a PodGroup that defines a PodGroupResourceClaim with the same Name and ResourceClaimTemplateName, this PodResourceClaim resolves to the ResourceClaim generated for the PodGroup. All pods in the group that define an equivalent PodResourceClaim matching the PodGroupResourceClaim's Name and ResourceClaimTemplateName share the same generated ResourceClaim. ResourceClaims generated for a PodGroup are owned by the PodGroup and their lifecycles are tied to the PodGroup instead of any individual pod.\n\nThis field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim.\n\nExactly one of ResourceClaimName and ResourceClaimTemplateName must be set.", "type": "string" } } @@ -7694,7 +7744,7 @@ "default": "" }, "resourceClaimName": { - "description": "ResourceClaimName is the name of the ResourceClaim that was generated for the Pod in the namespace of the Pod. If this is unset, then generating a ResourceClaim was not necessary. The pod.spec.resourceClaims entry can be ignored in this case.", + "description": "ResourceClaimName is the name of the ResourceClaim that was generated for the Pod in the namespace of the Pod.\n\nWhen the DRAWorkloadResourceClaims feature is enabled and the corresponding PodResourceClaim matches a PodGroupResourceClaim made by the Pod's PodGroup, then this is the name of the ResourceClaim generated and reserved for the PodGroup.\n\nIf this is unset, then generating a ResourceClaim was not necessary. The pod.spec.resourceClaims entry can be ignored in this case.", "type": "string" } } @@ -7713,6 +7763,23 @@ } } }, + "io.k8s.api.core.v1.PodSchedulingGroup": { + "description": "PodSchedulingGroup identifies the runtime scheduling group instance that a Pod belongs to. The scheduler uses this information to apply workload-aware scheduling semantics. Exactly one field must be specified.", + "type": "object", + "properties": { + "podGroupName": { + "description": "PodGroupName specifies the name of the standalone PodGroup object that represents the runtime instance of this group. Must be a DNS subdomain.", + "type": "string" + } + }, + "x-kubernetes-unions": [ + { + "fields-to-discriminateBy": { + "podGroupName": "PodGroupName" + } + } + ] + }, "io.k8s.api.core.v1.PodSecurityContext": { "description": "PodSecurityContext holds pod-level security attributes and common container settings. Some fields are also present in container.securityContext. Field values of container.securityContext take precedence over field values of PodSecurityContext.", "type": "object", @@ -7940,7 +8007,7 @@ "type": "boolean" }, "hostUsers": { - "description": "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.", + "description": "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.", "type": "boolean" }, "hostname": { @@ -8106,6 +8173,14 @@ "x-kubernetes-patch-merge-key": "name", "x-kubernetes-patch-strategy": "merge" }, + "schedulingGroup": { + "description": "SchedulingGroup provides a reference to the immediate scheduling runtime grouping object that this Pod belongs to. This field is used by the scheduler to identify the group and apply the correct group scheduling policies. The association with a group also impacts other lifecycle aspects of a Pod that are relevant in a wider context of scheduling like preemption, resource attachment, etc. If not specified, the Pod is treated as a single unit in all of these aspects. The group object referenced by this field may not exist at the time the Pod is created. This field is immutable, but a group object with the same name may be recreated with different policies. Doing this during pod scheduling may result in the placement not conforming to the expected policies.", + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.PodSchedulingGroup" + } + ] + }, "securityContext": { "description": "SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.", "allOf": [ @@ -8188,14 +8263,6 @@ "x-kubernetes-list-type": "map", "x-kubernetes-patch-merge-key": "name", "x-kubernetes-patch-strategy": "merge,retainKeys" - }, - "workloadRef": { - "description": "WorkloadRef provides a reference to the Workload object that this Pod belongs to. This field is used by the scheduler to identify the PodGroup and apply the correct group scheduling policies. The Workload object referenced by this field may not exist at the time the Pod is created. This field is immutable, but a Workload object with the same name may be recreated with different policies. Doing this during pod scheduling may result in the placement not conforming to the expected policies.", - "allOf": [ - { - "$ref": "#/components/schemas/io.k8s.api.core.v1.WorkloadReference" - } - ] } } }, @@ -8298,6 +8365,19 @@ "description": "A human readable message indicating details about why the pod is in this condition.", "type": "string" }, + "nodeAllocatableResourceClaimStatuses": { + "description": "NodeAllocatableResourceClaimStatuses contains the status of node-allocatable resources that were allocated for this pod through DRA claims. This includes resources currently reported in v1.Node `status.allocatable` that are not extended resources (see https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#extended-resources). Examples include \"cpu\", \"memory\", \"ephemeral-storage\", and hugepages.", + "type": "array", + "items": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.NodeAllocatableResourceClaimStatus" + } + ] + }, + "x-kubernetes-list-type": "atomic" + }, "nominatedNodeName": { "description": "nominatedNodeName is set only when this pod preempts other pods on the node, but it cannot be scheduled right away as preemption victims receive their graceful termination periods. This field does not guarantee that the pod will be scheduled on this node. Scheduler may decide to place the pod elsewhere if other nodes become available sooner. Scheduler may also decide to give the resources on this node to a higher priority pod that is created after preemption. As a result, this field may be different than PodSpec.nodeName when the pod is scheduled.", "type": "string" @@ -9201,6 +9281,10 @@ "description": "Health of the resource. can be one of:\n - Healthy: operates as normal\n - Unhealthy: reported unhealthy. We consider this a temporary health issue\n since we do not have a mechanism today to distinguish\n temporary and permanent issues.\n - Unknown: The status cannot be determined.\n For example, Device Plugin got unregistered and hasn't been re-registered since.\n\nIn future we may want to introduce the PermanentlyUnhealthy Status.", "type": "string" }, + "message": { + "description": "Message provides human-readable context for Health (e.g. \"ECC error count exceeded threshold\"). This field is populated by the kubelet when ResourceHealthStatusMessage is enabled if the DRA plugin returns a message, and is null otherwise.", + "type": "string" + }, "resourceID": { "description": "ResourceID is the unique identifier of the resource. See the ResourceID type for more information.", "type": "string", @@ -9872,7 +9956,7 @@ "type": "boolean" }, "procMount": { - "description": "procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows.\n\nPossible enum values:\n - `\"Default\"` uses the container runtime defaults for readonly and masked paths for /proc. Most container runtimes mask certain paths in /proc to avoid accidental security exposure of special devices or information.\n - `\"Unmasked\"` bypasses the default masking behavior of the container runtime and ensures the newly created /proc the container stays in tact with no modifications.", + "description": "procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. Note that this field cannot be set when spec.os.name is windows.\n\nPossible enum values:\n - `\"Default\"` uses the container runtime defaults for readonly and masked paths for /proc. Most container runtimes mask certain paths in /proc to avoid accidental security exposure of special devices or information.\n - `\"Unmasked\"` bypasses the default masking behavior of the container runtime and ensures the newly created /proc the container stays in tact with no modifications.", "type": "string", "enum": [ "Default", @@ -10913,7 +10997,7 @@ ] }, "image": { - "description": "image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided:\n\n- Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails.\n\nThe volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.", + "description": "image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided:\n\n- Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails.\n\nThe volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.", "allOf": [ { "$ref": "#/components/schemas/io.k8s.api.core.v1.ImageVolumeSource" @@ -10958,7 +11042,7 @@ ] }, "portworxVolume": { - "description": "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on.", + "description": "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver.", "allOf": [ { "$ref": "#/components/schemas/io.k8s.api.core.v1.PortworxVolumeSource" @@ -11113,6 +11197,14 @@ "recursiveReadOnly": { "description": "RecursiveReadOnly must be set to Disabled, Enabled, or unspecified (for non-readonly mounts). An IfPossible value in the original VolumeMount must be translated to Disabled or Enabled, depending on the mount result.", "type": "string" + }, + "volumeStatus": { + "description": "volumeStatus represents volume-type-specific status about the mounted volume.", + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.VolumeStatus" + } + ] } } }, @@ -11345,7 +11437,7 @@ ] }, "image": { - "description": "image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided:\n\n- Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails.\n\nThe volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.", + "description": "image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided:\n\n- Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails.\n\nThe volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.", "allOf": [ { "$ref": "#/components/schemas/io.k8s.api.core.v1.ImageVolumeSource" @@ -11385,7 +11477,7 @@ ] }, "portworxVolume": { - "description": "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on.", + "description": "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver.", "allOf": [ { "$ref": "#/components/schemas/io.k8s.api.core.v1.PortworxVolumeSource" @@ -11450,6 +11542,20 @@ } } }, + "io.k8s.api.core.v1.VolumeStatus": { + "description": "VolumeStatus represents the status of a mounted volume. At most one of its members must be specified.", + "type": "object", + "properties": { + "image": { + "description": "image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine.", + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.core.v1.ImageVolumeStatus" + } + ] + } + } + }, "io.k8s.api.core.v1.VsphereVirtualDiskVolumeSource": { "description": "Represents a vSphere volume resource.", "type": "object", @@ -11523,30 +11629,6 @@ } } }, - "io.k8s.api.core.v1.WorkloadReference": { - "description": "WorkloadReference identifies the Workload object and PodGroup membership that a Pod belongs to. The scheduler uses this information to apply workload-aware scheduling semantics.", - "type": "object", - "required": [ - "name", - "podGroup" - ], - "properties": { - "name": { - "description": "Name defines the name of the Workload object this Pod belongs to. Workload must be in the same namespace as the Pod. If it doesn't match any existing Workload, the Pod will remain unschedulable until a Workload object is created and observed by the kube-scheduler. It must be a DNS subdomain.", - "type": "string", - "default": "" - }, - "podGroup": { - "description": "PodGroup is the name of the PodGroup within the Workload that this Pod belongs to. If it doesn't match any existing PodGroup within the Workload, the Pod will remain unschedulable until the Workload object is recreated and observed by the kube-scheduler. It must be a DNS label.", - "type": "string", - "default": "" - }, - "podGroupReplicaKey": { - "description": "PodGroupReplicaKey specifies the replica key of the PodGroup to which this Pod belongs. It is used to distinguish pods belonging to different replicas of the same pod group. The pod group policy is applied separately to each replica. When set, it must be a DNS label.", - "type": "string" - } - } - }, "io.k8s.apimachinery.pkg.api.resource.Quantity": { "description": "Quantity is a fixed-point representation of a number. It provides convenient marshaling/unmarshaling in JSON and YAML, in addition to String() and AsInt64() accessors.\n\nThe serialization format is:\n\n``` \u003cquantity\u003e ::= \u003csignedNumber\u003e\u003csuffix\u003e\n\n\t(Note that \u003csuffix\u003e may be empty, from the \"\" case in \u003cdecimalSI\u003e.)\n\n\u003cdigit\u003e ::= 0 | 1 | ... | 9 \u003cdigits\u003e ::= \u003cdigit\u003e | \u003cdigit\u003e\u003cdigits\u003e \u003cnumber\u003e ::= \u003cdigits\u003e | \u003cdigits\u003e.\u003cdigits\u003e | \u003cdigits\u003e. | .\u003cdigits\u003e \u003csign\u003e ::= \"+\" | \"-\" \u003csignedNumber\u003e ::= \u003cnumber\u003e | \u003csign\u003e\u003cnumber\u003e \u003csuffix\u003e ::= \u003cbinarySI\u003e | \u003cdecimalExponent\u003e | \u003cdecimalSI\u003e \u003cbinarySI\u003e ::= Ki | Mi | Gi | Ti | Pi | Ei\n\n\t(International System of units; See: http://physics.nist.gov/cuu/Units/binary.html)\n\n\u003cdecimalSI\u003e ::= m | \"\" | k | M | G | T | P | E\n\n\t(Note that 1024 = 1Ki but 1000 = 1k; I didn't choose the capitalization.)\n\n\u003cdecimalExponent\u003e ::= \"e\" \u003csignedNumber\u003e | \"E\" \u003csignedNumber\u003e ```\n\nNo matter which of the three exponent forms is used, no quantity may represent a number greater than 2^63-1 in magnitude, nor may it have more than 3 decimal places. Numbers larger or more precise will be capped or rounded up. (E.g.: 0.1m will rounded up to 1m.) This may be extended in the future if we require larger or smaller quantities.\n\nWhen a Quantity is parsed from a string, it will remember the type of suffix it had, and will use the same type again when it is serialized.\n\nBefore serializing, Quantity will be put in \"canonical form\". This means that Exponent/suffix will be adjusted up or down (with a corresponding increase or decrease in Mantissa) such that:\n\n- No precision is lost - No fractional digits will be emitted - The exponent (or suffix) is as large as possible.\n\nThe sign will be omitted unless the number is negative.\n\nExamples:\n\n- 1.5 will be serialized as \"1500m\" - 1.5Gi will be serialized as \"1536Mi\"\n\nNote that the quantity will NEVER be internally represented by a floating point number. That is the whole point of this exercise.\n\nNon-canonical values will still parse as long as they are well formed, but will be re-emitted in their canonical form. (So always use canonical form, or don't diff.)\n\nThis format is intended to make it difficult to use these numbers without writing some sort of special handling code in the hopes that that will cause implementors to also use a fixed point implementation.", "oneOf": [ @@ -12261,6 +12343,14 @@ "selfLink": { "description": "Deprecated: selfLink is a legacy read-only field that is no longer populated by the system.", "type": "string" + }, + "shardInfo": { + "description": "shardInfo is set when the list is a filtered subset of the full collection, as selected by a shard selector on the request. It echoes back the selector so clients can verify which shard they received and merge sharded responses. Clients should not cache sharded list responses as a full representation of the collection.\n\nThis is an alpha field and requires enabling the ShardedListAndWatch feature gate.", + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ShardInfo" + } + ] } } }, @@ -12309,6 +12399,10 @@ "description": "`sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic \"Bookmark\" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `\"k8s.io/initial-events-end\": \"true\"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched.\n\nWhen `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan\n is interpreted as \"data at least as new as the provided `resourceVersion`\"\n and the bookmark event is send when the state is synced\n to a `resourceVersion` at least as fresh as the one provided by the ListOptions.\n If `resourceVersion` is unset, this is interpreted as \"consistent read\" and the\n bookmark event is send when the state is synced at least to the moment\n when request started being processed.\n- `resourceVersionMatch` set to any other value or unset\n Invalid error is returned.\n\nDefaults to true if `resourceVersion=\"\"` or `resourceVersion=\"0\"` (for backward compatibility reasons) and to false otherwise.", "type": "boolean" }, + "shardSelector": { + "description": "shardSelector restricts the list of returned objects using a CEL-based shard selector expression. The format uses the shardRange() function combined with || (logical OR) to specify one or more hash ranges:\n\n shardRange(object.metadata.uid, '0x0', '0x8000000000000000')\n shardRange(object.metadata.uid, '0x0', '0x8000000000000000') || shardRange(object.metadata.uid, '0x8000000000000000', '0x10000000000000000')\n\nField paths use CEL-style object-rooted syntax (e.g. \"object.metadata.uid\"), NOT the fieldSelector format (\"metadata.uid\"). Currently supported paths:\n - object.metadata.uid\n - object.metadata.namespace\n\nhexStart and hexEnd are single-quoted CEL string literals with a '0x' prefix, defining the inclusive lower and exclusive upper bounds over the 64-bit FNV-1a hash space. The full range is [0x0, 0x10000000000000000), where the exclusive upper bound equals 2^64.\n\nExamples:\n 2-shard split:\n shard 0: shardRange(object.metadata.uid, '0x0000000000000000', '0x8000000000000000')\n shard 1: shardRange(object.metadata.uid, '0x8000000000000000', '0x10000000000000000')\n 4-shard split:\n shard 0: shardRange(object.metadata.uid, '0x0000000000000000', '0x4000000000000000')\n shard 1: shardRange(object.metadata.uid, '0x4000000000000000', '0x8000000000000000')\n shard 2: shardRange(object.metadata.uid, '0x8000000000000000', '0xc000000000000000')\n shard 3: shardRange(object.metadata.uid, '0xc000000000000000', '0x10000000000000000')\n\nThis is an alpha field and requires enabling the ShardedListAndWatch feature gate.", + "type": "string" + }, "timeoutSeconds": { "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", "type": "integer", @@ -12673,6 +12767,20 @@ } } }, + "io.k8s.apimachinery.pkg.apis.meta.v1.ShardInfo": { + "description": "ShardInfo describes the shard selector that was applied to produce a list response. Its presence on a list response indicates the list is a filtered subset.", + "type": "object", + "required": [ + "selector" + ], + "properties": { + "selector": { + "description": "selector is the shard selector string from the request, echoed back so clients can verify which shard they received and merge responses from multiple shards.", + "type": "string", + "default": "" + } + } + }, "io.k8s.apimachinery.pkg.apis.meta.v1.Status": { "description": "Status is a return value for calls that don't return other objects.", "type": "object", diff --git a/api/python_api/kubeflow_trainer_api/models/__init__.py b/api/python_api/kubeflow_trainer_api/models/__init__.py index 1c05b8cc7c..a20e6b7dbd 100644 --- a/api/python_api/kubeflow_trainer_api/models/__init__.py +++ b/api/python_api/kubeflow_trainer_api/models/__init__.py @@ -135,6 +135,7 @@ from kubeflow_trainer_api.models.io_k8s_api_core_v1_iscsi_persistent_volume_source import IoK8sApiCoreV1ISCSIPersistentVolumeSource from kubeflow_trainer_api.models.io_k8s_api_core_v1_iscsi_volume_source import IoK8sApiCoreV1ISCSIVolumeSource from kubeflow_trainer_api.models.io_k8s_api_core_v1_image_volume_source import IoK8sApiCoreV1ImageVolumeSource +from kubeflow_trainer_api.models.io_k8s_api_core_v1_image_volume_status import IoK8sApiCoreV1ImageVolumeStatus from kubeflow_trainer_api.models.io_k8s_api_core_v1_key_to_path import IoK8sApiCoreV1KeyToPath from kubeflow_trainer_api.models.io_k8s_api_core_v1_lifecycle import IoK8sApiCoreV1Lifecycle from kubeflow_trainer_api.models.io_k8s_api_core_v1_lifecycle_handler import IoK8sApiCoreV1LifecycleHandler @@ -158,6 +159,7 @@ from kubeflow_trainer_api.models.io_k8s_api_core_v1_node import IoK8sApiCoreV1Node from kubeflow_trainer_api.models.io_k8s_api_core_v1_node_address import IoK8sApiCoreV1NodeAddress from kubeflow_trainer_api.models.io_k8s_api_core_v1_node_affinity import IoK8sApiCoreV1NodeAffinity +from kubeflow_trainer_api.models.io_k8s_api_core_v1_node_allocatable_resource_claim_status import IoK8sApiCoreV1NodeAllocatableResourceClaimStatus from kubeflow_trainer_api.models.io_k8s_api_core_v1_node_condition import IoK8sApiCoreV1NodeCondition from kubeflow_trainer_api.models.io_k8s_api_core_v1_node_config_source import IoK8sApiCoreV1NodeConfigSource from kubeflow_trainer_api.models.io_k8s_api_core_v1_node_config_status import IoK8sApiCoreV1NodeConfigStatus @@ -210,6 +212,7 @@ from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_resource_claim import IoK8sApiCoreV1PodResourceClaim from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_resource_claim_status import IoK8sApiCoreV1PodResourceClaimStatus from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_scheduling_gate import IoK8sApiCoreV1PodSchedulingGate +from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_scheduling_group import IoK8sApiCoreV1PodSchedulingGroup from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_security_context import IoK8sApiCoreV1PodSecurityContext from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_signature import IoK8sApiCoreV1PodSignature from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_spec import IoK8sApiCoreV1PodSpec @@ -288,10 +291,10 @@ from kubeflow_trainer_api.models.io_k8s_api_core_v1_volume_projection import IoK8sApiCoreV1VolumeProjection from kubeflow_trainer_api.models.io_k8s_api_core_v1_volume_resource_requirements import IoK8sApiCoreV1VolumeResourceRequirements from kubeflow_trainer_api.models.io_k8s_api_core_v1_volume_source import IoK8sApiCoreV1VolumeSource +from kubeflow_trainer_api.models.io_k8s_api_core_v1_volume_status import IoK8sApiCoreV1VolumeStatus from kubeflow_trainer_api.models.io_k8s_api_core_v1_vsphere_virtual_disk_volume_source import IoK8sApiCoreV1VsphereVirtualDiskVolumeSource from kubeflow_trainer_api.models.io_k8s_api_core_v1_weighted_pod_affinity_term import IoK8sApiCoreV1WeightedPodAffinityTerm from kubeflow_trainer_api.models.io_k8s_api_core_v1_windows_security_context_options import IoK8sApiCoreV1WindowsSecurityContextOptions -from kubeflow_trainer_api.models.io_k8s_api_core_v1_workload_reference import IoK8sApiCoreV1WorkloadReference from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_api_resource_quantity import IoK8sApimachineryPkgApiResourceQuantity from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_apis_meta_v1_api_group import IoK8sApimachineryPkgApisMetaV1APIGroup from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_apis_meta_v1_api_group_list import IoK8sApimachineryPkgApisMetaV1APIGroupList @@ -325,6 +328,7 @@ from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_apis_meta_v1_preconditions import IoK8sApimachineryPkgApisMetaV1Preconditions from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_apis_meta_v1_root_paths import IoK8sApimachineryPkgApisMetaV1RootPaths from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_apis_meta_v1_server_address_by_client_cidr import IoK8sApimachineryPkgApisMetaV1ServerAddressByClientCIDR +from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_apis_meta_v1_shard_info import IoK8sApimachineryPkgApisMetaV1ShardInfo from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_apis_meta_v1_status import IoK8sApimachineryPkgApisMetaV1Status from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_apis_meta_v1_status_cause import IoK8sApimachineryPkgApisMetaV1StatusCause from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_apis_meta_v1_status_details import IoK8sApimachineryPkgApisMetaV1StatusDetails diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_autoscaling_v2_horizontal_pod_autoscaler.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_autoscaling_v2_horizontal_pod_autoscaler.py index 4077ef3173..cdb944d04a 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_autoscaling_v2_horizontal_pod_autoscaler.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_autoscaling_v2_horizontal_pod_autoscaler.py @@ -32,7 +32,7 @@ class IoK8sApiAutoscalingV2HorizontalPodAutoscaler(BaseModel): api_version: Optional[StrictStr] = Field(default=None, 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", alias="apiVersion") kind: Optional[StrictStr] = Field(default=None, 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") metadata: Optional[IoK8sApimachineryPkgApisMetaV1ObjectMeta] = Field(default=None, description="metadata is the standard object metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata") - spec: Optional[IoK8sApiAutoscalingV2HorizontalPodAutoscalerSpec] = Field(default=None, description="spec is the specification for the behaviour of the autoscaler. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status.") + spec: IoK8sApiAutoscalingV2HorizontalPodAutoscalerSpec = Field(description="spec is the specification for the behaviour of the autoscaler. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status.") status: Optional[IoK8sApiAutoscalingV2HorizontalPodAutoscalerStatus] = Field(default=None, description="status is the current information about the autoscaler.") __properties: ClassVar[List[str]] = ["apiVersion", "kind", "metadata", "spec", "status"] diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_batch_v1_cron_job.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_batch_v1_cron_job.py index 0a36b33ccb..99862bc16e 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_batch_v1_cron_job.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_batch_v1_cron_job.py @@ -32,7 +32,7 @@ class IoK8sApiBatchV1CronJob(BaseModel): api_version: Optional[StrictStr] = Field(default=None, 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", alias="apiVersion") kind: Optional[StrictStr] = Field(default=None, 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") metadata: Optional[IoK8sApimachineryPkgApisMetaV1ObjectMeta] = Field(default=None, description="Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata") - spec: Optional[IoK8sApiBatchV1CronJobSpec] = Field(default=None, description="Specification of the desired behavior of a cron job, including the schedule. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status") + spec: IoK8sApiBatchV1CronJobSpec = Field(description="Specification of the desired behavior of a cron job, including the schedule. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status") status: Optional[IoK8sApiBatchV1CronJobStatus] = Field(default=None, description="Current status of a cron job. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status") __properties: ClassVar[List[str]] = ["apiVersion", "kind", "metadata", "spec", "status"] diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_image_volume_status.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_image_volume_status.py new file mode 100644 index 0000000000..27e3ef7fe3 --- /dev/null +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_image_volume_status.py @@ -0,0 +1,87 @@ +# coding: utf-8 + +""" + Kubeflow Trainer OpenAPI Spec + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: unversioned + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self + +class IoK8sApiCoreV1ImageVolumeStatus(BaseModel): + """ + ImageVolumeStatus represents the image-based volume status. + """ # noqa: E501 + image_ref: StrictStr = Field(description="ImageRef is the digest of the image used for this volume. It should have a value that's similar to the pod's status.containerStatuses[i].imageID. The ImageRef length should not exceed 256 characters.", alias="imageRef") + __properties: ClassVar[List[str]] = ["imageRef"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of IoK8sApiCoreV1ImageVolumeStatus from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of IoK8sApiCoreV1ImageVolumeStatus from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "imageRef": obj.get("imageRef") + }) + return _obj + + diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_node_allocatable_resource_claim_status.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_node_allocatable_resource_claim_status.py new file mode 100644 index 0000000000..9ead49383e --- /dev/null +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_node_allocatable_resource_claim_status.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" + Kubeflow Trainer OpenAPI Spec + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: unversioned + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_api_resource_quantity import IoK8sApimachineryPkgApiResourceQuantity +from typing import Optional, Set +from typing_extensions import Self + +class IoK8sApiCoreV1NodeAllocatableResourceClaimStatus(BaseModel): + """ + NodeAllocatableResourceClaimStatus describes the status of node allocatable resources allocated via DRA. + """ # noqa: E501 + containers: Optional[List[StrictStr]] = Field(default=None, description="Containers lists the names of all containers in this pod that reference the claim.") + resource_claim_name: StrictStr = Field(description="ResourceClaimName is the resource claim referenced by the pod that resulted in this node allocatable resource allocation.", alias="resourceClaimName") + resources: Dict[str, IoK8sApimachineryPkgApiResourceQuantity] = Field(description="Resources is a map of the node-allocatable resource name to the aggregate quantity allocated to the claim.") + __properties: ClassVar[List[str]] = ["containers", "resourceClaimName", "resources"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of IoK8sApiCoreV1NodeAllocatableResourceClaimStatus from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each value in resources (dict) + _field_dict = {} + if self.resources: + for _key_resources in self.resources: + if self.resources[_key_resources]: + _field_dict[_key_resources] = self.resources[_key_resources].to_dict() + _dict['resources'] = _field_dict + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of IoK8sApiCoreV1NodeAllocatableResourceClaimStatus from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "containers": obj.get("containers"), + "resourceClaimName": obj.get("resourceClaimName") if obj.get("resourceClaimName") is not None else '', + "resources": dict( + (_k, IoK8sApimachineryPkgApiResourceQuantity.from_dict(_v)) + for _k, _v in obj["resources"].items() + ) + if obj.get("resources") is not None + else None + }) + return _obj + + diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_persistent_volume_source.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_persistent_volume_source.py index a709d1b7e8..879c20f516 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_persistent_volume_source.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_persistent_volume_source.py @@ -64,7 +64,7 @@ class IoK8sApiCoreV1PersistentVolumeSource(BaseModel): local: Optional[IoK8sApiCoreV1LocalVolumeSource] = Field(default=None, description="local represents directly-attached storage with node affinity") nfs: Optional[IoK8sApiCoreV1NFSVolumeSource] = Field(default=None, description="nfs represents an NFS mount on the host. Provisioned by an admin. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs") photon_persistent_disk: Optional[IoK8sApiCoreV1PhotonPersistentDiskVolumeSource] = Field(default=None, description="photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine. Deprecated: PhotonPersistentDisk is deprecated and the in-tree photonPersistentDisk type is no longer supported.", alias="photonPersistentDisk") - portworx_volume: Optional[IoK8sApiCoreV1PortworxVolumeSource] = Field(default=None, description="portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on.", alias="portworxVolume") + portworx_volume: Optional[IoK8sApiCoreV1PortworxVolumeSource] = Field(default=None, description="portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver.", alias="portworxVolume") quobyte: Optional[IoK8sApiCoreV1QuobyteVolumeSource] = Field(default=None, description="quobyte represents a Quobyte mount on the host that shares a pod's lifetime. Deprecated: Quobyte is deprecated and the in-tree quobyte type is no longer supported.") rbd: Optional[IoK8sApiCoreV1RBDPersistentVolumeSource] = Field(default=None, description="rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. More info: https://examples.k8s.io/volumes/rbd/README.md") scale_io: Optional[IoK8sApiCoreV1ScaleIOPersistentVolumeSource] = Field(default=None, description="scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. Deprecated: ScaleIO is deprecated and the in-tree scaleIO type is no longer supported.", alias="scaleIO") diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_persistent_volume_spec.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_persistent_volume_spec.py index 34d03e7689..701a459dcf 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_persistent_volume_spec.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_persistent_volume_spec.py @@ -73,7 +73,7 @@ class IoK8sApiCoreV1PersistentVolumeSpec(BaseModel): node_affinity: Optional[IoK8sApiCoreV1VolumeNodeAffinity] = Field(default=None, description="nodeAffinity defines constraints that limit what nodes this volume can be accessed from. This field influences the scheduling of pods that use this volume. This field is mutable if MutablePVNodeAffinity feature gate is enabled.", alias="nodeAffinity") persistent_volume_reclaim_policy: Optional[StrictStr] = Field(default=None, description="persistentVolumeReclaimPolicy defines what happens to a persistent volume when released from its claim. Valid options are Retain (default for manually created PersistentVolumes), Delete (default for dynamically provisioned PersistentVolumes), and Recycle (deprecated). Recycle must be supported by the volume plugin underlying this PersistentVolume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming Possible enum values: - `\"Delete\"` means the volume will be deleted from Kubernetes on release from its claim. The volume plugin must support Deletion. - `\"Recycle\"` means the volume will be recycled back into the pool of unbound persistent volumes on release from its claim. The volume plugin must support Recycling. - `\"Retain\"` means the volume will be left in its current phase (Released) for manual reclamation by the administrator. The default policy is Retain.", alias="persistentVolumeReclaimPolicy") photon_persistent_disk: Optional[IoK8sApiCoreV1PhotonPersistentDiskVolumeSource] = Field(default=None, description="photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine. Deprecated: PhotonPersistentDisk is deprecated and the in-tree photonPersistentDisk type is no longer supported.", alias="photonPersistentDisk") - portworx_volume: Optional[IoK8sApiCoreV1PortworxVolumeSource] = Field(default=None, description="portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on.", alias="portworxVolume") + portworx_volume: Optional[IoK8sApiCoreV1PortworxVolumeSource] = Field(default=None, description="portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver.", alias="portworxVolume") quobyte: Optional[IoK8sApiCoreV1QuobyteVolumeSource] = Field(default=None, description="quobyte represents a Quobyte mount on the host that shares a pod's lifetime. Deprecated: Quobyte is deprecated and the in-tree quobyte type is no longer supported.") rbd: Optional[IoK8sApiCoreV1RBDPersistentVolumeSource] = Field(default=None, description="rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. More info: https://examples.k8s.io/volumes/rbd/README.md") scale_io: Optional[IoK8sApiCoreV1ScaleIOPersistentVolumeSource] = Field(default=None, description="scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. Deprecated: ScaleIO is deprecated and the in-tree scaleIO type is no longer supported.", alias="scaleIO") diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_condition.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_condition.py index 43f9518136..5a10f482a6 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_condition.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_condition.py @@ -30,7 +30,7 @@ class IoK8sApiCoreV1PodCondition(BaseModel): last_probe_time: Optional[datetime] = Field(default=None, description="Last time we probed the condition.", alias="lastProbeTime") last_transition_time: Optional[datetime] = Field(default=None, description="Last time the condition transitioned from one status to another.", alias="lastTransitionTime") message: Optional[StrictStr] = Field(default=None, description="Human-readable message indicating details about last transition.") - observed_generation: Optional[StrictInt] = Field(default=None, description="If set, this represents the .metadata.generation that the pod condition was set based upon. The PodObservedGenerationTracking feature gate must be enabled to use this field.", alias="observedGeneration") + observed_generation: Optional[StrictInt] = Field(default=None, description="If set, this represents the .metadata.generation that the pod condition was set based upon.", alias="observedGeneration") reason: Optional[StrictStr] = Field(default=None, description="Unique, one-word, CamelCase reason for the condition's last transition.") status: StrictStr = Field(description="Status is the status of the condition. Can be True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions") type: StrictStr = Field(description="Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions") diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_resource_claim.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_resource_claim.py index d0868b2ebc..6d9b8d761b 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_resource_claim.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_resource_claim.py @@ -24,11 +24,11 @@ class IoK8sApiCoreV1PodResourceClaim(BaseModel): """ - PodResourceClaim references exactly one ResourceClaim, either directly or by naming a ResourceClaimTemplate which is then turned into a ResourceClaim for the pod. 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. + PodResourceClaim references exactly one ResourceClaim, either directly or by naming a ResourceClaimTemplate which is then turned into a ResourceClaim for the pod. 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. When the DRAWorkloadResourceClaims feature gate is enabled and this Pod belongs to a PodGroup, a PodResourceClaim is matched to a PodGroupResourceClaim if all of their fields are equal (Name, ResourceClaimName, and ResourceClaimTemplateName). A matched claim references a single ResourceClaim shared across all Pods in the PodGroup, reserved for the PodGroup in ResourceClaimStatus.ReservedFor rather than for individual Pods. """ # noqa: E501 name: StrictStr = Field(description="Name uniquely identifies this resource claim inside the pod. This must be a DNS_LABEL.") resource_claim_name: Optional[StrictStr] = Field(default=None, description="ResourceClaimName is the name of a ResourceClaim object in the same namespace as this pod. Exactly one of ResourceClaimName and ResourceClaimTemplateName must be set.", alias="resourceClaimName") - resource_claim_template_name: Optional[StrictStr] = Field(default=None, description="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 pod name and resource name, along with a generated component, will be used to form a unique name for the ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim. Exactly one of ResourceClaimName and ResourceClaimTemplateName must be set.", alias="resourceClaimTemplateName") + resource_claim_template_name: Optional[StrictStr] = Field(default=None, description="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 pod name and resource name, along with a generated component, will be used to form a unique name for the ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. When the DRAWorkloadResourceClaims feature gate is enabled and the pod belongs to a PodGroup that defines a PodGroupResourceClaim with the same Name and ResourceClaimTemplateName, this PodResourceClaim resolves to the ResourceClaim generated for the PodGroup. All pods in the group that define an equivalent PodResourceClaim matching the PodGroupResourceClaim's Name and ResourceClaimTemplateName share the same generated ResourceClaim. ResourceClaims generated for a PodGroup are owned by the PodGroup and their lifecycles are tied to the PodGroup instead of any individual pod. This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim. Exactly one of ResourceClaimName and ResourceClaimTemplateName must be set.", alias="resourceClaimTemplateName") __properties: ClassVar[List[str]] = ["name", "resourceClaimName", "resourceClaimTemplateName"] model_config = ConfigDict( diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_resource_claim_status.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_resource_claim_status.py index ace89259dd..ebc63ad8a5 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_resource_claim_status.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_resource_claim_status.py @@ -27,7 +27,7 @@ class IoK8sApiCoreV1PodResourceClaimStatus(BaseModel): PodResourceClaimStatus is stored in the PodStatus for each PodResourceClaim which references a ResourceClaimTemplate. It stores the generated name for the corresponding ResourceClaim. """ # noqa: E501 name: StrictStr = Field(description="Name uniquely identifies this resource claim inside the pod. This must match the name of an entry in pod.spec.resourceClaims, which implies that the string must be a DNS_LABEL.") - resource_claim_name: Optional[StrictStr] = Field(default=None, description="ResourceClaimName is the name of the ResourceClaim that was generated for the Pod in the namespace of the Pod. If this is unset, then generating a ResourceClaim was not necessary. The pod.spec.resourceClaims entry can be ignored in this case.", alias="resourceClaimName") + resource_claim_name: Optional[StrictStr] = Field(default=None, description="ResourceClaimName is the name of the ResourceClaim that was generated for the Pod in the namespace of the Pod. When the DRAWorkloadResourceClaims feature is enabled and the corresponding PodResourceClaim matches a PodGroupResourceClaim made by the Pod's PodGroup, then this is the name of the ResourceClaim generated and reserved for the PodGroup. If this is unset, then generating a ResourceClaim was not necessary. The pod.spec.resourceClaims entry can be ignored in this case.", alias="resourceClaimName") __properties: ClassVar[List[str]] = ["name", "resourceClaimName"] model_config = ConfigDict( diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_scheduling_group.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_scheduling_group.py new file mode 100644 index 0000000000..f634741859 --- /dev/null +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_scheduling_group.py @@ -0,0 +1,87 @@ +# coding: utf-8 + +""" + Kubeflow Trainer OpenAPI Spec + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: unversioned + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self + +class IoK8sApiCoreV1PodSchedulingGroup(BaseModel): + """ + PodSchedulingGroup identifies the runtime scheduling group instance that a Pod belongs to. The scheduler uses this information to apply workload-aware scheduling semantics. Exactly one field must be specified. + """ # noqa: E501 + pod_group_name: Optional[StrictStr] = Field(default=None, description="PodGroupName specifies the name of the standalone PodGroup object that represents the runtime instance of this group. Must be a DNS subdomain.", alias="podGroupName") + __properties: ClassVar[List[str]] = ["podGroupName"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of IoK8sApiCoreV1PodSchedulingGroup from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of IoK8sApiCoreV1PodSchedulingGroup from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "podGroupName": obj.get("podGroupName") + }) + return _obj + + diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_spec.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_spec.py index 4c8a0ed394..0565f98756 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_spec.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_spec.py @@ -29,12 +29,12 @@ from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_readiness_gate import IoK8sApiCoreV1PodReadinessGate from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_resource_claim import IoK8sApiCoreV1PodResourceClaim from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_scheduling_gate import IoK8sApiCoreV1PodSchedulingGate +from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_scheduling_group import IoK8sApiCoreV1PodSchedulingGroup from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_security_context import IoK8sApiCoreV1PodSecurityContext from kubeflow_trainer_api.models.io_k8s_api_core_v1_resource_requirements import IoK8sApiCoreV1ResourceRequirements from kubeflow_trainer_api.models.io_k8s_api_core_v1_toleration import IoK8sApiCoreV1Toleration from kubeflow_trainer_api.models.io_k8s_api_core_v1_topology_spread_constraint import IoK8sApiCoreV1TopologySpreadConstraint from kubeflow_trainer_api.models.io_k8s_api_core_v1_volume import IoK8sApiCoreV1Volume -from kubeflow_trainer_api.models.io_k8s_api_core_v1_workload_reference import IoK8sApiCoreV1WorkloadReference from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_api_resource_quantity import IoK8sApimachineryPkgApiResourceQuantity from typing import Optional, Set from typing_extensions import Self @@ -55,7 +55,7 @@ class IoK8sApiCoreV1PodSpec(BaseModel): host_ipc: Optional[StrictBool] = Field(default=None, description="Use the host's ipc namespace. Optional: Default to false.", alias="hostIPC") host_network: Optional[StrictBool] = Field(default=None, description="Host networking requested for this pod. Use the host's network namespace. When using HostNetwork you should specify ports so the scheduler is aware. When `hostNetwork` is true, specified `hostPort` fields in port definitions must match `containerPort`, and unspecified `hostPort` fields in port definitions are defaulted to match `containerPort`. Default to false.", alias="hostNetwork") host_pid: Optional[StrictBool] = Field(default=None, description="Use the host's pid namespace. Optional: Default to false.", alias="hostPID") - host_users: Optional[StrictBool] = Field(default=None, description="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.", alias="hostUsers") + host_users: Optional[StrictBool] = Field(default=None, description="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.", alias="hostUsers") hostname: Optional[StrictStr] = Field(default=None, description="Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value.") hostname_override: Optional[StrictStr] = Field(default=None, description="HostnameOverride specifies an explicit override for the pod's hostname as perceived by the pod. This field only specifies the pod's hostname and does not affect its DNS records. When this field is set to a non-empty string: - It takes precedence over the values set in `hostname` and `subdomain`. - The Pod's hostname will be set to this value. - `setHostnameAsFQDN` must be nil or set to false. - `hostNetwork` must be set to false. This field must be a valid DNS subdomain as defined in RFC 1123 and contain at most 64 characters. Requires the HostnameOverride feature gate to be enabled.", alias="hostnameOverride") image_pull_secrets: Optional[List[IoK8sApiCoreV1LocalObjectReference]] = Field(default=None, description="ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod", alias="imagePullSecrets") @@ -74,6 +74,7 @@ class IoK8sApiCoreV1PodSpec(BaseModel): runtime_class_name: Optional[StrictStr] = Field(default=None, description="RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. If unset or empty, the \"legacy\" RuntimeClass will be used, which is an implicit class with an empty definition that uses the default runtime handler. More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class", alias="runtimeClassName") scheduler_name: Optional[StrictStr] = Field(default=None, description="If specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler.", alias="schedulerName") scheduling_gates: Optional[List[IoK8sApiCoreV1PodSchedulingGate]] = Field(default=None, description="SchedulingGates is an opaque list of values that if specified will block scheduling the pod. If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the scheduler will not attempt to schedule the pod. SchedulingGates can only be set at pod creation time, and be removed only afterwards.", alias="schedulingGates") + scheduling_group: Optional[IoK8sApiCoreV1PodSchedulingGroup] = Field(default=None, description="SchedulingGroup provides a reference to the immediate scheduling runtime grouping object that this Pod belongs to. This field is used by the scheduler to identify the group and apply the correct group scheduling policies. The association with a group also impacts other lifecycle aspects of a Pod that are relevant in a wider context of scheduling like preemption, resource attachment, etc. If not specified, the Pod is treated as a single unit in all of these aspects. The group object referenced by this field may not exist at the time the Pod is created. This field is immutable, but a group object with the same name may be recreated with different policies. Doing this during pod scheduling may result in the placement not conforming to the expected policies.", alias="schedulingGroup") security_context: Optional[IoK8sApiCoreV1PodSecurityContext] = Field(default=None, description="SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.", alias="securityContext") service_account: Optional[StrictStr] = Field(default=None, description="DeprecatedServiceAccount is a deprecated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead.", alias="serviceAccount") service_account_name: Optional[StrictStr] = Field(default=None, description="ServiceAccountName is the name of the ServiceAccount to use to run this pod. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/", alias="serviceAccountName") @@ -84,8 +85,7 @@ class IoK8sApiCoreV1PodSpec(BaseModel): tolerations: Optional[List[IoK8sApiCoreV1Toleration]] = Field(default=None, description="If specified, the pod's tolerations.") topology_spread_constraints: Optional[List[IoK8sApiCoreV1TopologySpreadConstraint]] = Field(default=None, description="TopologySpreadConstraints describes how a group of pods ought to spread across topology domains. Scheduler will schedule pods in a way which abides by the constraints. All topologySpreadConstraints are ANDed.", alias="topologySpreadConstraints") volumes: Optional[List[IoK8sApiCoreV1Volume]] = Field(default=None, description="List of volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes") - workload_ref: Optional[IoK8sApiCoreV1WorkloadReference] = Field(default=None, description="WorkloadRef provides a reference to the Workload object that this Pod belongs to. This field is used by the scheduler to identify the PodGroup and apply the correct group scheduling policies. The Workload object referenced by this field may not exist at the time the Pod is created. This field is immutable, but a Workload object with the same name may be recreated with different policies. Doing this during pod scheduling may result in the placement not conforming to the expected policies.", alias="workloadRef") - __properties: ClassVar[List[str]] = ["activeDeadlineSeconds", "affinity", "automountServiceAccountToken", "containers", "dnsConfig", "dnsPolicy", "enableServiceLinks", "ephemeralContainers", "hostAliases", "hostIPC", "hostNetwork", "hostPID", "hostUsers", "hostname", "hostnameOverride", "imagePullSecrets", "initContainers", "nodeName", "nodeSelector", "os", "overhead", "preemptionPolicy", "priority", "priorityClassName", "readinessGates", "resourceClaims", "resources", "restartPolicy", "runtimeClassName", "schedulerName", "schedulingGates", "securityContext", "serviceAccount", "serviceAccountName", "setHostnameAsFQDN", "shareProcessNamespace", "subdomain", "terminationGracePeriodSeconds", "tolerations", "topologySpreadConstraints", "volumes", "workloadRef"] + __properties: ClassVar[List[str]] = ["activeDeadlineSeconds", "affinity", "automountServiceAccountToken", "containers", "dnsConfig", "dnsPolicy", "enableServiceLinks", "ephemeralContainers", "hostAliases", "hostIPC", "hostNetwork", "hostPID", "hostUsers", "hostname", "hostnameOverride", "imagePullSecrets", "initContainers", "nodeName", "nodeSelector", "os", "overhead", "preemptionPolicy", "priority", "priorityClassName", "readinessGates", "resourceClaims", "resources", "restartPolicy", "runtimeClassName", "schedulerName", "schedulingGates", "schedulingGroup", "securityContext", "serviceAccount", "serviceAccountName", "setHostnameAsFQDN", "shareProcessNamespace", "subdomain", "terminationGracePeriodSeconds", "tolerations", "topologySpreadConstraints", "volumes"] @field_validator('dns_policy') def dns_policy_validate_enum(cls, value): @@ -231,6 +231,9 @@ def to_dict(self) -> Dict[str, Any]: if _item_scheduling_gates: _items.append(_item_scheduling_gates.to_dict()) _dict['schedulingGates'] = _items + # override the default output from pydantic by calling `to_dict()` of scheduling_group + if self.scheduling_group: + _dict['schedulingGroup'] = self.scheduling_group.to_dict() # override the default output from pydantic by calling `to_dict()` of security_context if self.security_context: _dict['securityContext'] = self.security_context.to_dict() @@ -255,9 +258,6 @@ def to_dict(self) -> Dict[str, Any]: if _item_volumes: _items.append(_item_volumes.to_dict()) _dict['volumes'] = _items - # override the default output from pydantic by calling `to_dict()` of workload_ref - if self.workload_ref: - _dict['workloadRef'] = self.workload_ref.to_dict() return _dict @classmethod @@ -306,6 +306,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "runtimeClassName": obj.get("runtimeClassName"), "schedulerName": obj.get("schedulerName"), "schedulingGates": [IoK8sApiCoreV1PodSchedulingGate.from_dict(_item) for _item in obj["schedulingGates"]] if obj.get("schedulingGates") is not None else None, + "schedulingGroup": IoK8sApiCoreV1PodSchedulingGroup.from_dict(obj["schedulingGroup"]) if obj.get("schedulingGroup") is not None else None, "securityContext": IoK8sApiCoreV1PodSecurityContext.from_dict(obj["securityContext"]) if obj.get("securityContext") is not None else None, "serviceAccount": obj.get("serviceAccount"), "serviceAccountName": obj.get("serviceAccountName"), @@ -315,8 +316,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "terminationGracePeriodSeconds": obj.get("terminationGracePeriodSeconds"), "tolerations": [IoK8sApiCoreV1Toleration.from_dict(_item) for _item in obj["tolerations"]] if obj.get("tolerations") is not None else None, "topologySpreadConstraints": [IoK8sApiCoreV1TopologySpreadConstraint.from_dict(_item) for _item in obj["topologySpreadConstraints"]] if obj.get("topologySpreadConstraints") is not None else None, - "volumes": [IoK8sApiCoreV1Volume.from_dict(_item) for _item in obj["volumes"]] if obj.get("volumes") is not None else None, - "workloadRef": IoK8sApiCoreV1WorkloadReference.from_dict(obj["workloadRef"]) if obj.get("workloadRef") is not None else None + "volumes": [IoK8sApiCoreV1Volume.from_dict(_item) for _item in obj["volumes"]] if obj.get("volumes") is not None else None }) return _obj diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_status.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_status.py index b019f18e39..48802fcac7 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_status.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_pod_status.py @@ -22,6 +22,7 @@ from typing import Any, ClassVar, Dict, List, Optional from kubeflow_trainer_api.models.io_k8s_api_core_v1_container_status import IoK8sApiCoreV1ContainerStatus from kubeflow_trainer_api.models.io_k8s_api_core_v1_host_ip import IoK8sApiCoreV1HostIP +from kubeflow_trainer_api.models.io_k8s_api_core_v1_node_allocatable_resource_claim_status import IoK8sApiCoreV1NodeAllocatableResourceClaimStatus from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_condition import IoK8sApiCoreV1PodCondition from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_extended_resource_claim_status import IoK8sApiCoreV1PodExtendedResourceClaimStatus from kubeflow_trainer_api.models.io_k8s_api_core_v1_pod_ip import IoK8sApiCoreV1PodIP @@ -44,6 +45,7 @@ class IoK8sApiCoreV1PodStatus(BaseModel): host_ips: Optional[List[IoK8sApiCoreV1HostIP]] = Field(default=None, description="hostIPs holds the IP addresses allocated to the host. If this field is specified, the first entry must match the hostIP field. This list is empty if the pod has not started yet. A pod can be assigned to a node that has a problem in kubelet which in turns means that HostIPs will not be updated even if there is a node is assigned to this pod.", alias="hostIPs") init_container_statuses: Optional[List[IoK8sApiCoreV1ContainerStatus]] = Field(default=None, description="Statuses of init containers in this pod. The most recent successful non-restartable init container will have ready = true, the most recently started container will have startTime set. Each init container in the pod should have at most one status in this list, and all statuses should be for containers in the pod. However this is not enforced. If a status for a non-existent container is present in the list, or the list has duplicate names, the behavior of various Kubernetes components is not defined and those statuses might be ignored. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-and-container-status", alias="initContainerStatuses") message: Optional[StrictStr] = Field(default=None, description="A human readable message indicating details about why the pod is in this condition.") + node_allocatable_resource_claim_statuses: Optional[List[IoK8sApiCoreV1NodeAllocatableResourceClaimStatus]] = Field(default=None, description="NodeAllocatableResourceClaimStatuses contains the status of node-allocatable resources that were allocated for this pod through DRA claims. This includes resources currently reported in v1.Node `status.allocatable` that are not extended resources (see https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#extended-resources). Examples include \"cpu\", \"memory\", \"ephemeral-storage\", and hugepages.", alias="nodeAllocatableResourceClaimStatuses") nominated_node_name: Optional[StrictStr] = Field(default=None, description="nominatedNodeName is set only when this pod preempts other pods on the node, but it cannot be scheduled right away as preemption victims receive their graceful termination periods. This field does not guarantee that the pod will be scheduled on this node. Scheduler may decide to place the pod elsewhere if other nodes become available sooner. Scheduler may also decide to give the resources on this node to a higher priority pod that is created after preemption. As a result, this field may be different than PodSpec.nodeName when the pod is scheduled.", alias="nominatedNodeName") observed_generation: Optional[StrictInt] = Field(default=None, description="If set, this represents the .metadata.generation that the pod status was set based upon. The PodObservedGenerationTracking feature gate must be enabled to use this field.", alias="observedGeneration") phase: Optional[StrictStr] = Field(default=None, description="The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. The conditions array, the reason and message fields, and the individual container status arrays contain more detail about the pod's status. There are five possible phase values: Pending: The pod has been accepted by the Kubernetes system, but one or more of the container images has not been created. This includes time before being scheduled as well as time spent downloading images over the network, which could take a while. Running: The pod has been bound to a node, and all of the containers have been created. At least one container is still running, or is in the process of starting or restarting. Succeeded: All containers in the pod have terminated in success, and will not be restarted. Failed: All containers in the pod have terminated, and at least one container has terminated in failure. The container either exited with non-zero status or was terminated by the system. Unknown: For some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase Possible enum values: - `\"Failed\"` means that all containers in the pod have terminated, and at least one container has terminated in a failure (exited with a non-zero exit code or was stopped by the system). - `\"Pending\"` means the pod has been accepted by the system, but one or more of the containers has not been started. This includes time before being bound to a node, as well as time spent pulling images onto the host. - `\"Running\"` means the pod has been bound to a node and all of the containers have been started. At least one container is still running or is in the process of being restarted. - `\"Succeeded\"` means that all containers in the pod have voluntarily terminated with a container exit code of 0, and the system is not going to restart any of these containers. - `\"Unknown\"` means that for some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod. Deprecated: It isn't being set since 2015 (74da3b14b0c0f658b3bb8d2def5094686d0e9095)") @@ -55,7 +57,7 @@ class IoK8sApiCoreV1PodStatus(BaseModel): resource_claim_statuses: Optional[List[IoK8sApiCoreV1PodResourceClaimStatus]] = Field(default=None, description="Status of resource claims.", alias="resourceClaimStatuses") resources: Optional[IoK8sApiCoreV1ResourceRequirements] = Field(default=None, description="Resources represents the compute resource requests and limits that have been applied at the pod level if pod-level requests or limits are set in PodSpec.Resources") start_time: Optional[datetime] = Field(default=None, description="RFC 3339 date and time at which the object was acknowledged by the Kubelet. This is before the Kubelet pulled the container image(s) for the pod.", alias="startTime") - __properties: ClassVar[List[str]] = ["allocatedResources", "conditions", "containerStatuses", "ephemeralContainerStatuses", "extendedResourceClaimStatus", "hostIP", "hostIPs", "initContainerStatuses", "message", "nominatedNodeName", "observedGeneration", "phase", "podIP", "podIPs", "qosClass", "reason", "resize", "resourceClaimStatuses", "resources", "startTime"] + __properties: ClassVar[List[str]] = ["allocatedResources", "conditions", "containerStatuses", "ephemeralContainerStatuses", "extendedResourceClaimStatus", "hostIP", "hostIPs", "initContainerStatuses", "message", "nodeAllocatableResourceClaimStatuses", "nominatedNodeName", "observedGeneration", "phase", "podIP", "podIPs", "qosClass", "reason", "resize", "resourceClaimStatuses", "resources", "startTime"] @field_validator('phase') def phase_validate_enum(cls, value): @@ -161,6 +163,13 @@ def to_dict(self) -> Dict[str, Any]: if _item_init_container_statuses: _items.append(_item_init_container_statuses.to_dict()) _dict['initContainerStatuses'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in node_allocatable_resource_claim_statuses (list) + _items = [] + if self.node_allocatable_resource_claim_statuses: + for _item_node_allocatable_resource_claim_statuses in self.node_allocatable_resource_claim_statuses: + if _item_node_allocatable_resource_claim_statuses: + _items.append(_item_node_allocatable_resource_claim_statuses.to_dict()) + _dict['nodeAllocatableResourceClaimStatuses'] = _items # override the default output from pydantic by calling `to_dict()` of each item in pod_ips (list) _items = [] if self.pod_ips: @@ -204,6 +213,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "hostIPs": [IoK8sApiCoreV1HostIP.from_dict(_item) for _item in obj["hostIPs"]] if obj.get("hostIPs") is not None else None, "initContainerStatuses": [IoK8sApiCoreV1ContainerStatus.from_dict(_item) for _item in obj["initContainerStatuses"]] if obj.get("initContainerStatuses") is not None else None, "message": obj.get("message"), + "nodeAllocatableResourceClaimStatuses": [IoK8sApiCoreV1NodeAllocatableResourceClaimStatus.from_dict(_item) for _item in obj["nodeAllocatableResourceClaimStatuses"]] if obj.get("nodeAllocatableResourceClaimStatuses") is not None else None, "nominatedNodeName": obj.get("nominatedNodeName"), "observedGeneration": obj.get("observedGeneration"), "phase": obj.get("phase"), diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_resource_health.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_resource_health.py index 60052bba56..35860900f0 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_resource_health.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_resource_health.py @@ -27,8 +27,9 @@ class IoK8sApiCoreV1ResourceHealth(BaseModel): ResourceHealth represents the health of a resource. It has the latest device health information. This is a part of KEP https://kep.k8s.io/4680. """ # noqa: E501 health: Optional[StrictStr] = Field(default=None, description="Health of the resource. can be one of: - Healthy: operates as normal - Unhealthy: reported unhealthy. We consider this a temporary health issue since we do not have a mechanism today to distinguish temporary and permanent issues. - Unknown: The status cannot be determined. For example, Device Plugin got unregistered and hasn't been re-registered since. In future we may want to introduce the PermanentlyUnhealthy Status.") + message: Optional[StrictStr] = Field(default=None, description="Message provides human-readable context for Health (e.g. \"ECC error count exceeded threshold\"). This field is populated by the kubelet when ResourceHealthStatusMessage is enabled if the DRA plugin returns a message, and is null otherwise.") resource_id: StrictStr = Field(description="ResourceID is the unique identifier of the resource. See the ResourceID type for more information.", alias="resourceID") - __properties: ClassVar[List[str]] = ["health", "resourceID"] + __properties: ClassVar[List[str]] = ["health", "message", "resourceID"] model_config = ConfigDict( populate_by_name=True, @@ -82,6 +83,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "health": obj.get("health"), + "message": obj.get("message"), "resourceID": obj.get("resourceID") if obj.get("resourceID") is not None else '' }) return _obj diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_security_context.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_security_context.py index f4e45f7474..696e26a2db 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_security_context.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_security_context.py @@ -35,7 +35,7 @@ class IoK8sApiCoreV1SecurityContext(BaseModel): app_armor_profile: Optional[IoK8sApiCoreV1AppArmorProfile] = Field(default=None, description="appArmorProfile is the AppArmor options to use by this container. If set, this profile overrides the pod's appArmorProfile. Note that this field cannot be set when spec.os.name is windows.", alias="appArmorProfile") capabilities: Optional[IoK8sApiCoreV1Capabilities] = Field(default=None, description="The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime. Note that this field cannot be set when spec.os.name is windows.") privileged: Optional[StrictBool] = Field(default=None, description="Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. Note that this field cannot be set when spec.os.name is windows.") - proc_mount: Optional[StrictStr] = Field(default=None, description="procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. Possible enum values: - `\"Default\"` uses the container runtime defaults for readonly and masked paths for /proc. Most container runtimes mask certain paths in /proc to avoid accidental security exposure of special devices or information. - `\"Unmasked\"` bypasses the default masking behavior of the container runtime and ensures the newly created /proc the container stays in tact with no modifications.", alias="procMount") + proc_mount: Optional[StrictStr] = Field(default=None, description="procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. Note that this field cannot be set when spec.os.name is windows. Possible enum values: - `\"Default\"` uses the container runtime defaults for readonly and masked paths for /proc. Most container runtimes mask certain paths in /proc to avoid accidental security exposure of special devices or information. - `\"Unmasked\"` bypasses the default masking behavior of the container runtime and ensures the newly created /proc the container stays in tact with no modifications.", alias="procMount") read_only_root_filesystem: Optional[StrictBool] = Field(default=None, description="Whether this container has a read-only root filesystem. Default is false. Note that this field cannot be set when spec.os.name is windows.", alias="readOnlyRootFilesystem") run_as_group: Optional[StrictInt] = Field(default=None, description="The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. Note that this field cannot be set when spec.os.name is windows.", alias="runAsGroup") run_as_non_root: Optional[StrictBool] = Field(default=None, description="Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.", alias="runAsNonRoot") diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume.py index 9a386ccc68..06781b8f3f 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume.py @@ -73,13 +73,13 @@ class IoK8sApiCoreV1Volume(BaseModel): git_repo: Optional[IoK8sApiCoreV1GitRepoVolumeSource] = Field(default=None, description="gitRepo represents a git repository at a particular revision. Deprecated: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", alias="gitRepo") glusterfs: Optional[IoK8sApiCoreV1GlusterfsVolumeSource] = Field(default=None, description="glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.") host_path: Optional[IoK8sApiCoreV1HostPathVolumeSource] = Field(default=None, description="hostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are allowed to see the host machine. Most containers will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", alias="hostPath") - image: Optional[IoK8sApiCoreV1ImageVolumeSource] = Field(default=None, description="image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided: - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.") + image: Optional[IoK8sApiCoreV1ImageVolumeSource] = Field(default=None, description="image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided: - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.") iscsi: Optional[IoK8sApiCoreV1ISCSIVolumeSource] = Field(default=None, description="iscsi represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi") name: StrictStr = Field(description="name of the volume. Must be a DNS_LABEL and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names") nfs: Optional[IoK8sApiCoreV1NFSVolumeSource] = Field(default=None, description="nfs represents an NFS mount on the host that shares a pod's lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs") persistent_volume_claim: Optional[IoK8sApiCoreV1PersistentVolumeClaimVolumeSource] = Field(default=None, description="persistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", alias="persistentVolumeClaim") photon_persistent_disk: Optional[IoK8sApiCoreV1PhotonPersistentDiskVolumeSource] = Field(default=None, description="photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine. Deprecated: PhotonPersistentDisk is deprecated and the in-tree photonPersistentDisk type is no longer supported.", alias="photonPersistentDisk") - portworx_volume: Optional[IoK8sApiCoreV1PortworxVolumeSource] = Field(default=None, description="portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on.", alias="portworxVolume") + portworx_volume: Optional[IoK8sApiCoreV1PortworxVolumeSource] = Field(default=None, description="portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver.", alias="portworxVolume") projected: Optional[IoK8sApiCoreV1ProjectedVolumeSource] = Field(default=None, description="projected items for all in one resources secrets, configmaps, and downward API") quobyte: Optional[IoK8sApiCoreV1QuobyteVolumeSource] = Field(default=None, description="quobyte represents a Quobyte mount on the host that shares a pod's lifetime. Deprecated: Quobyte is deprecated and the in-tree quobyte type is no longer supported.") rbd: Optional[IoK8sApiCoreV1RBDVolumeSource] = Field(default=None, description="rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.") diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume_mount_status.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume_mount_status.py index 6551d9dcf8..b9a5f148a8 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume_mount_status.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume_mount_status.py @@ -19,6 +19,7 @@ from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr from typing import Any, ClassVar, Dict, List, Optional +from kubeflow_trainer_api.models.io_k8s_api_core_v1_volume_status import IoK8sApiCoreV1VolumeStatus from typing import Optional, Set from typing_extensions import Self @@ -30,7 +31,8 @@ class IoK8sApiCoreV1VolumeMountStatus(BaseModel): name: StrictStr = Field(description="Name corresponds to the name of the original VolumeMount.") read_only: Optional[StrictBool] = Field(default=None, description="ReadOnly corresponds to the original VolumeMount.", alias="readOnly") recursive_read_only: Optional[StrictStr] = Field(default=None, description="RecursiveReadOnly must be set to Disabled, Enabled, or unspecified (for non-readonly mounts). An IfPossible value in the original VolumeMount must be translated to Disabled or Enabled, depending on the mount result.", alias="recursiveReadOnly") - __properties: ClassVar[List[str]] = ["mountPath", "name", "readOnly", "recursiveReadOnly"] + volume_status: Optional[IoK8sApiCoreV1VolumeStatus] = Field(default=None, description="volumeStatus represents volume-type-specific status about the mounted volume.", alias="volumeStatus") + __properties: ClassVar[List[str]] = ["mountPath", "name", "readOnly", "recursiveReadOnly", "volumeStatus"] model_config = ConfigDict( populate_by_name=True, @@ -71,6 +73,9 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of volume_status + if self.volume_status: + _dict['volumeStatus'] = self.volume_status.to_dict() return _dict @classmethod @@ -86,7 +91,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "mountPath": obj.get("mountPath") if obj.get("mountPath") is not None else '', "name": obj.get("name") if obj.get("name") is not None else '', "readOnly": obj.get("readOnly"), - "recursiveReadOnly": obj.get("recursiveReadOnly") + "recursiveReadOnly": obj.get("recursiveReadOnly"), + "volumeStatus": IoK8sApiCoreV1VolumeStatus.from_dict(obj["volumeStatus"]) if obj.get("volumeStatus") is not None else None }) return _obj diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume_source.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume_source.py index e5e55249e6..a30592bb3a 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume_source.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume_source.py @@ -73,12 +73,12 @@ class IoK8sApiCoreV1VolumeSource(BaseModel): git_repo: Optional[IoK8sApiCoreV1GitRepoVolumeSource] = Field(default=None, description="gitRepo represents a git repository at a particular revision. Deprecated: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod's container.", alias="gitRepo") glusterfs: Optional[IoK8sApiCoreV1GlusterfsVolumeSource] = Field(default=None, description="glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported.") host_path: Optional[IoK8sApiCoreV1HostPathVolumeSource] = Field(default=None, description="hostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are allowed to see the host machine. Most containers will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", alias="hostPath") - image: Optional[IoK8sApiCoreV1ImageVolumeSource] = Field(default=None, description="image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided: - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.") + image: Optional[IoK8sApiCoreV1ImageVolumeSource] = Field(default=None, description="image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided: - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.") iscsi: Optional[IoK8sApiCoreV1ISCSIVolumeSource] = Field(default=None, description="iscsi represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi") nfs: Optional[IoK8sApiCoreV1NFSVolumeSource] = Field(default=None, description="nfs represents an NFS mount on the host that shares a pod's lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs") persistent_volume_claim: Optional[IoK8sApiCoreV1PersistentVolumeClaimVolumeSource] = Field(default=None, description="persistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims", alias="persistentVolumeClaim") photon_persistent_disk: Optional[IoK8sApiCoreV1PhotonPersistentDiskVolumeSource] = Field(default=None, description="photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine. Deprecated: PhotonPersistentDisk is deprecated and the in-tree photonPersistentDisk type is no longer supported.", alias="photonPersistentDisk") - portworx_volume: Optional[IoK8sApiCoreV1PortworxVolumeSource] = Field(default=None, description="portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on.", alias="portworxVolume") + portworx_volume: Optional[IoK8sApiCoreV1PortworxVolumeSource] = Field(default=None, description="portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver.", alias="portworxVolume") projected: Optional[IoK8sApiCoreV1ProjectedVolumeSource] = Field(default=None, description="projected items for all in one resources secrets, configmaps, and downward API") quobyte: Optional[IoK8sApiCoreV1QuobyteVolumeSource] = Field(default=None, description="quobyte represents a Quobyte mount on the host that shares a pod's lifetime. Deprecated: Quobyte is deprecated and the in-tree quobyte type is no longer supported.") rbd: Optional[IoK8sApiCoreV1RBDVolumeSource] = Field(default=None, description="rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported.") diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume_status.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume_status.py new file mode 100644 index 0000000000..c1c596d076 --- /dev/null +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_api_core_v1_volume_status.py @@ -0,0 +1,91 @@ +# coding: utf-8 + +""" + Kubeflow Trainer OpenAPI Spec + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: unversioned + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field +from typing import Any, ClassVar, Dict, List, Optional +from kubeflow_trainer_api.models.io_k8s_api_core_v1_image_volume_status import IoK8sApiCoreV1ImageVolumeStatus +from typing import Optional, Set +from typing_extensions import Self + +class IoK8sApiCoreV1VolumeStatus(BaseModel): + """ + VolumeStatus represents the status of a mounted volume. At most one of its members must be specified. + """ # noqa: E501 + image: Optional[IoK8sApiCoreV1ImageVolumeStatus] = Field(default=None, description="image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine.") + __properties: ClassVar[List[str]] = ["image"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of IoK8sApiCoreV1VolumeStatus from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of image + if self.image: + _dict['image'] = self.image.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of IoK8sApiCoreV1VolumeStatus from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "image": IoK8sApiCoreV1ImageVolumeStatus.from_dict(obj["image"]) if obj.get("image") is not None else None + }) + return _obj + + diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_apimachinery_pkg_apis_meta_v1_list_meta.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_apimachinery_pkg_apis_meta_v1_list_meta.py index 56133e582d..aa02fa691f 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_apimachinery_pkg_apis_meta_v1_list_meta.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_apimachinery_pkg_apis_meta_v1_list_meta.py @@ -19,6 +19,7 @@ from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr from typing import Any, ClassVar, Dict, List, Optional +from kubeflow_trainer_api.models.io_k8s_apimachinery_pkg_apis_meta_v1_shard_info import IoK8sApimachineryPkgApisMetaV1ShardInfo from typing import Optional, Set from typing_extensions import Self @@ -30,7 +31,8 @@ class IoK8sApimachineryPkgApisMetaV1ListMeta(BaseModel): remaining_item_count: Optional[StrictInt] = Field(default=None, 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.", alias="remainingItemCount") resource_version: Optional[StrictStr] = Field(default=None, 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", alias="resourceVersion") self_link: Optional[StrictStr] = Field(default=None, description="Deprecated: selfLink is a legacy read-only field that is no longer populated by the system.", alias="selfLink") - __properties: ClassVar[List[str]] = ["continue", "remainingItemCount", "resourceVersion", "selfLink"] + shard_info: Optional[IoK8sApimachineryPkgApisMetaV1ShardInfo] = Field(default=None, description="shardInfo is set when the list is a filtered subset of the full collection, as selected by a shard selector on the request. It echoes back the selector so clients can verify which shard they received and merge sharded responses. Clients should not cache sharded list responses as a full representation of the collection. This is an alpha field and requires enabling the ShardedListAndWatch feature gate.", alias="shardInfo") + __properties: ClassVar[List[str]] = ["continue", "remainingItemCount", "resourceVersion", "selfLink", "shardInfo"] model_config = ConfigDict( populate_by_name=True, @@ -71,6 +73,9 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of shard_info + if self.shard_info: + _dict['shardInfo'] = self.shard_info.to_dict() return _dict @classmethod @@ -86,7 +91,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "continue": obj.get("continue"), "remainingItemCount": obj.get("remainingItemCount"), "resourceVersion": obj.get("resourceVersion"), - "selfLink": obj.get("selfLink") + "selfLink": obj.get("selfLink"), + "shardInfo": IoK8sApimachineryPkgApisMetaV1ShardInfo.from_dict(obj["shardInfo"]) if obj.get("shardInfo") is not None else None }) return _obj diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_apimachinery_pkg_apis_meta_v1_list_options.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_apimachinery_pkg_apis_meta_v1_list_options.py index f48368091b..b2c042781e 100644 --- a/api/python_api/kubeflow_trainer_api/models/io_k8s_apimachinery_pkg_apis_meta_v1_list_options.py +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_apimachinery_pkg_apis_meta_v1_list_options.py @@ -36,9 +36,10 @@ class IoK8sApimachineryPkgApisMetaV1ListOptions(BaseModel): resource_version: Optional[StrictStr] = Field(default=None, 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. Defaults to unset", alias="resourceVersion") resource_version_match: Optional[StrictStr] = Field(default=None, 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. Defaults to unset", alias="resourceVersionMatch") send_initial_events: Optional[StrictBool] = Field(default=None, description="`sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic \"Bookmark\" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `\"k8s.io/initial-events-end\": \"true\"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as \"data at least as new as the provided `resourceVersion`\" and the bookmark event is send when the state is synced to a `resourceVersion` at least as fresh as the one provided by the ListOptions. If `resourceVersion` is unset, this is interpreted as \"consistent read\" and the bookmark event is send when the state is synced at least to the moment when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. Defaults to true if `resourceVersion=\"\"` or `resourceVersion=\"0\"` (for backward compatibility reasons) and to false otherwise.", alias="sendInitialEvents") + shard_selector: Optional[StrictStr] = Field(default=None, description="shardSelector restricts the list of returned objects using a CEL-based shard selector expression. The format uses the shardRange() function combined with || (logical OR) to specify one or more hash ranges: shardRange(object.metadata.uid, '0x0', '0x8000000000000000') shardRange(object.metadata.uid, '0x0', '0x8000000000000000') || shardRange(object.metadata.uid, '0x8000000000000000', '0x10000000000000000') Field paths use CEL-style object-rooted syntax (e.g. \"object.metadata.uid\"), NOT the fieldSelector format (\"metadata.uid\"). Currently supported paths: - object.metadata.uid - object.metadata.namespace hexStart and hexEnd are single-quoted CEL string literals with a '0x' prefix, defining the inclusive lower and exclusive upper bounds over the 64-bit FNV-1a hash space. The full range is [0x0, 0x10000000000000000), where the exclusive upper bound equals 2^64. Examples: 2-shard split: shard 0: shardRange(object.metadata.uid, '0x0000000000000000', '0x8000000000000000') shard 1: shardRange(object.metadata.uid, '0x8000000000000000', '0x10000000000000000') 4-shard split: shard 0: shardRange(object.metadata.uid, '0x0000000000000000', '0x4000000000000000') shard 1: shardRange(object.metadata.uid, '0x4000000000000000', '0x8000000000000000') shard 2: shardRange(object.metadata.uid, '0x8000000000000000', '0xc000000000000000') shard 3: shardRange(object.metadata.uid, '0xc000000000000000', '0x10000000000000000') This is an alpha field and requires enabling the ShardedListAndWatch feature gate.", alias="shardSelector") timeout_seconds: Optional[StrictInt] = Field(default=None, description="Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", alias="timeoutSeconds") watch: Optional[StrictBool] = Field(default=None, description="Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.") - __properties: ClassVar[List[str]] = ["allowWatchBookmarks", "apiVersion", "continue", "fieldSelector", "kind", "labelSelector", "limit", "resourceVersion", "resourceVersionMatch", "sendInitialEvents", "timeoutSeconds", "watch"] + __properties: ClassVar[List[str]] = ["allowWatchBookmarks", "apiVersion", "continue", "fieldSelector", "kind", "labelSelector", "limit", "resourceVersion", "resourceVersionMatch", "sendInitialEvents", "shardSelector", "timeoutSeconds", "watch"] model_config = ConfigDict( populate_by_name=True, @@ -101,6 +102,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "resourceVersion": obj.get("resourceVersion"), "resourceVersionMatch": obj.get("resourceVersionMatch"), "sendInitialEvents": obj.get("sendInitialEvents"), + "shardSelector": obj.get("shardSelector"), "timeoutSeconds": obj.get("timeoutSeconds"), "watch": obj.get("watch") }) diff --git a/api/python_api/kubeflow_trainer_api/models/io_k8s_apimachinery_pkg_apis_meta_v1_shard_info.py b/api/python_api/kubeflow_trainer_api/models/io_k8s_apimachinery_pkg_apis_meta_v1_shard_info.py new file mode 100644 index 0000000000..2b030f8d3a --- /dev/null +++ b/api/python_api/kubeflow_trainer_api/models/io_k8s_apimachinery_pkg_apis_meta_v1_shard_info.py @@ -0,0 +1,87 @@ +# coding: utf-8 + +""" + Kubeflow Trainer OpenAPI Spec + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + + The version of the OpenAPI document: unversioned + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self + +class IoK8sApimachineryPkgApisMetaV1ShardInfo(BaseModel): + """ + ShardInfo describes the shard selector that was applied to produce a list response. Its presence on a list response indicates the list is a filtered subset. + """ # noqa: E501 + selector: StrictStr = Field(description="selector is the shard selector string from the request, echoed back so clients can verify which shard they received and merge responses from multiple shards.") + __properties: ClassVar[List[str]] = ["selector"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of IoK8sApimachineryPkgApisMetaV1ShardInfo from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of IoK8sApimachineryPkgApisMetaV1ShardInfo from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "selector": obj.get("selector") if obj.get("selector") is not None else '' + }) + return _obj + + diff --git a/charts/kubeflow-trainer/crds/trainer.kubeflow.org_clustertrainingruntimes.yaml b/charts/kubeflow-trainer/crds/trainer.kubeflow.org_clustertrainingruntimes.yaml index b66b3f1ab6..e947075b5b 100644 --- a/charts/kubeflow-trainer/crds/trainer.kubeflow.org_clustertrainingruntimes.yaml +++ b/charts/kubeflow-trainer/crds/trainer.kubeflow.org_clustertrainingruntimes.yaml @@ -3037,7 +3037,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -4728,7 +4727,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -5240,7 +5238,6 @@ spec: 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. type: boolean hostname: description: |- @@ -6501,7 +6498,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -7097,6 +7093,14 @@ spec: 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. + + When the DRAWorkloadResourceClaims feature gate is enabled and this Pod + belongs to a PodGroup, a PodResourceClaim is matched to a + PodGroupResourceClaim if all of their fields are equal (Name, + ResourceClaimName, and ResourceClaimTemplateName). A matched claim references + a single ResourceClaim shared across all Pods in the PodGroup, reserved for + the PodGroup in ResourceClaimStatus.ReservedFor rather than for individual + Pods. properties: name: description: |- @@ -7122,6 +7126,16 @@ spec: generated component, will be used to form a unique name for the ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. + When the DRAWorkloadResourceClaims feature gate is enabled and the pod + belongs to a PodGroup that defines a PodGroupResourceClaim with the same + Name and ResourceClaimTemplateName, this PodResourceClaim resolves to the + ResourceClaim generated for the PodGroup. All pods in the group that + define an equivalent PodResourceClaim matching the + PodGroupResourceClaim's Name and ResourceClaimTemplateName share the same + generated ResourceClaim. ResourceClaims generated for a PodGroup are + owned by the PodGroup and their lifecycles are tied to the PodGroup + instead of any individual pod. + This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim. @@ -7249,6 +7263,28 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + schedulingGroup: + description: |- + SchedulingGroup provides a reference to the immediate scheduling runtime + grouping object that this Pod belongs to. + This field is used by the scheduler to identify the group and apply the + correct group scheduling policies. The association with a group also + impacts other lifecycle aspects of a Pod that are relevant in a wider context + of scheduling like preemption, resource attachment, etc. If not specified, + the Pod is treated as a single unit in all of these aspects. + The group object referenced by this field may not exist at the time the + Pod is created. + This field is immutable, but a group object with the same name may be + recreated with different policies. Doing this during pod scheduling + may result in the placement not conforming to the expected policies. + properties: + podGroupName: + description: |- + PodGroupName specifies the name of the standalone PodGroup object + that represents the runtime instance of this group. + Must be a DNS subdomain. + type: string + type: object securityContext: description: |- SecurityContext holds pod-level security attributes and common container settings. @@ -8773,7 +8809,7 @@ spec: A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. - The volume will be mounted read-only (ro) and non-executable files (noexec). + The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: @@ -8951,8 +8987,7 @@ spec: description: |- portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type - are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate - is on. + are redirected to the pxd.portworx.com CSI driver. properties: fsType: description: |- @@ -9872,42 +9907,6 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map - workloadRef: - description: |- - WorkloadRef provides a reference to the Workload object that this Pod belongs to. - This field is used by the scheduler to identify the PodGroup and apply the - correct group scheduling policies. The Workload object referenced - by this field may not exist at the time the Pod is created. - This field is immutable, but a Workload object with the same name - may be recreated with different policies. Doing this during pod scheduling - may result in the placement not conforming to the expected policies. - properties: - name: - description: |- - Name defines the name of the Workload object this Pod belongs to. - Workload must be in the same namespace as the Pod. - If it doesn't match any existing Workload, the Pod will remain unschedulable - until a Workload object is created and observed by the kube-scheduler. - It must be a DNS subdomain. - type: string - podGroup: - description: |- - PodGroup is the name of the PodGroup within the Workload that this Pod - belongs to. If it doesn't match any existing PodGroup within the Workload, - the Pod will remain unschedulable until the Workload object is recreated - and observed by the kube-scheduler. It must be a DNS label. - type: string - podGroupReplicaKey: - description: |- - PodGroupReplicaKey specifies the replica key of the PodGroup to which this - Pod belongs. It is used to distinguish pods belonging to different replicas - of the same pod group. The pod group policy is applied separately to each replica. - When set, it must be a DNS label. - type: string - required: - - name - - podGroup - type: object required: - containers type: object diff --git a/charts/kubeflow-trainer/crds/trainer.kubeflow.org_trainingruntimes.yaml b/charts/kubeflow-trainer/crds/trainer.kubeflow.org_trainingruntimes.yaml index 08cf086562..cf2d0654ff 100644 --- a/charts/kubeflow-trainer/crds/trainer.kubeflow.org_trainingruntimes.yaml +++ b/charts/kubeflow-trainer/crds/trainer.kubeflow.org_trainingruntimes.yaml @@ -3037,7 +3037,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -4728,7 +4727,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -5240,7 +5238,6 @@ spec: 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. type: boolean hostname: description: |- @@ -6501,7 +6498,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -7097,6 +7093,14 @@ spec: 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. + + When the DRAWorkloadResourceClaims feature gate is enabled and this Pod + belongs to a PodGroup, a PodResourceClaim is matched to a + PodGroupResourceClaim if all of their fields are equal (Name, + ResourceClaimName, and ResourceClaimTemplateName). A matched claim references + a single ResourceClaim shared across all Pods in the PodGroup, reserved for + the PodGroup in ResourceClaimStatus.ReservedFor rather than for individual + Pods. properties: name: description: |- @@ -7122,6 +7126,16 @@ spec: generated component, will be used to form a unique name for the ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. + When the DRAWorkloadResourceClaims feature gate is enabled and the pod + belongs to a PodGroup that defines a PodGroupResourceClaim with the same + Name and ResourceClaimTemplateName, this PodResourceClaim resolves to the + ResourceClaim generated for the PodGroup. All pods in the group that + define an equivalent PodResourceClaim matching the + PodGroupResourceClaim's Name and ResourceClaimTemplateName share the same + generated ResourceClaim. ResourceClaims generated for a PodGroup are + owned by the PodGroup and their lifecycles are tied to the PodGroup + instead of any individual pod. + This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim. @@ -7249,6 +7263,28 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + schedulingGroup: + description: |- + SchedulingGroup provides a reference to the immediate scheduling runtime + grouping object that this Pod belongs to. + This field is used by the scheduler to identify the group and apply the + correct group scheduling policies. The association with a group also + impacts other lifecycle aspects of a Pod that are relevant in a wider context + of scheduling like preemption, resource attachment, etc. If not specified, + the Pod is treated as a single unit in all of these aspects. + The group object referenced by this field may not exist at the time the + Pod is created. + This field is immutable, but a group object with the same name may be + recreated with different policies. Doing this during pod scheduling + may result in the placement not conforming to the expected policies. + properties: + podGroupName: + description: |- + PodGroupName specifies the name of the standalone PodGroup object + that represents the runtime instance of this group. + Must be a DNS subdomain. + type: string + type: object securityContext: description: |- SecurityContext holds pod-level security attributes and common container settings. @@ -8773,7 +8809,7 @@ spec: A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. - The volume will be mounted read-only (ro) and non-executable files (noexec). + The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: @@ -8951,8 +8987,7 @@ spec: description: |- portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type - are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate - is on. + are redirected to the pxd.portworx.com CSI driver. properties: fsType: description: |- @@ -9872,42 +9907,6 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map - workloadRef: - description: |- - WorkloadRef provides a reference to the Workload object that this Pod belongs to. - This field is used by the scheduler to identify the PodGroup and apply the - correct group scheduling policies. The Workload object referenced - by this field may not exist at the time the Pod is created. - This field is immutable, but a Workload object with the same name - may be recreated with different policies. Doing this during pod scheduling - may result in the placement not conforming to the expected policies. - properties: - name: - description: |- - Name defines the name of the Workload object this Pod belongs to. - Workload must be in the same namespace as the Pod. - If it doesn't match any existing Workload, the Pod will remain unschedulable - until a Workload object is created and observed by the kube-scheduler. - It must be a DNS subdomain. - type: string - podGroup: - description: |- - PodGroup is the name of the PodGroup within the Workload that this Pod - belongs to. If it doesn't match any existing PodGroup within the Workload, - the Pod will remain unschedulable until the Workload object is recreated - and observed by the kube-scheduler. It must be a DNS label. - type: string - podGroupReplicaKey: - description: |- - PodGroupReplicaKey specifies the replica key of the PodGroup to which this - Pod belongs. It is used to distinguish pods belonging to different replicas - of the same pod group. The pod group policy is applied separately to each replica. - When set, it must be a DNS label. - type: string - required: - - name - - podGroup - type: object required: - containers type: object diff --git a/charts/kubeflow-trainer/crds/trainer.kubeflow.org_trainjobs.yaml b/charts/kubeflow-trainer/crds/trainer.kubeflow.org_trainjobs.yaml index acac158aa8..a4418a0b52 100644 --- a/charts/kubeflow-trainer/crds/trainer.kubeflow.org_trainjobs.yaml +++ b/charts/kubeflow-trainer/crds/trainer.kubeflow.org_trainjobs.yaml @@ -2038,7 +2038,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -2621,7 +2620,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -4283,7 +4281,7 @@ spec: A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. - The volume will be mounted read-only (ro) and non-executable files (noexec). + The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: @@ -4471,8 +4469,7 @@ spec: description: |- portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type - are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate - is on. + are redirected to the pxd.portworx.com CSI driver. properties: fsType: description: |- diff --git a/go.mod b/go.mod index 176acc15bb..bd2b3e63e3 100644 --- a/go.mod +++ b/go.mod @@ -11,17 +11,17 @@ require ( github.com/open-policy-agent/cert-controller v0.16.0 go.uber.org/zap v1.28.0 golang.org/x/crypto v0.50.0 - k8s.io/api v0.35.2 - k8s.io/apimachinery v0.35.2 - k8s.io/apiserver v0.35.2 - k8s.io/client-go v0.35.2 - k8s.io/code-generator v0.35.2 - k8s.io/component-base v0.35.2 - k8s.io/component-helpers v0.35.2 - k8s.io/klog/v2 v2.130.1 - k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 - k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 - sigs.k8s.io/controller-runtime v0.23.3 + k8s.io/api v0.36.0 + k8s.io/apimachinery v0.36.0 + k8s.io/apiserver v0.36.0 + k8s.io/client-go v0.36.0 + k8s.io/code-generator v0.36.0 + k8s.io/component-base v0.36.0 + k8s.io/component-helpers v0.36.0 + k8s.io/klog/v2 v2.140.0 + k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a + k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 + sigs.k8s.io/controller-runtime v0.24.0 sigs.k8s.io/jobset v0.11.1 sigs.k8s.io/kind v0.31.0 sigs.k8s.io/scheduler-plugins v0.34.4-devel-sg @@ -37,7 +37,7 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.12.2 // indirect + github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect @@ -47,7 +47,6 @@ require ( github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.1 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect - github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 // indirect github.com/google/uuid v1.6.0 // indirect @@ -64,9 +63,9 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.23.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.66.1 // indirect - github.com/prometheus/procfs v0.16.1 // indirect - github.com/spf13/cobra v1.10.0 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/procfs v0.19.2 // indirect + github.com/spf13/cobra v1.10.2 // indirect github.com/spf13/pflag v1.0.9 // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/otel v1.41.0 // indirect @@ -82,14 +81,14 @@ require ( golang.org/x/sys v0.43.0 // indirect golang.org/x/term v0.42.0 // indirect golang.org/x/text v0.36.0 // indirect - golang.org/x/time v0.11.0 // indirect + golang.org/x/time v0.14.0 // indirect golang.org/x/tools v0.44.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/protobuf v1.36.8 // indirect + google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.35.2 // indirect + k8s.io/apiextensions-apiserver v0.36.0 // indirect k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/randfill v1.0.0 // indirect diff --git a/go.sum b/go.sum index 4e3c5b961f..f57fb624c1 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= -github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= +github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= @@ -49,8 +49,6 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= -github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= -github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -115,16 +113,15 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= -github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= -github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= -github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= +github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.10.0 h1:a5/WeUlSDCvV5a45ljW2ZFtV0bTDpkfSAj3uqB6Sc+0= -github.com/spf13/cobra v1.10.0/go.mod h1:9dhySC7dnTtEiqzmqfkLj47BslqLCUPMXjG2lj/NgoE= -github.com/spf13/pflag v1.0.8/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -176,8 +173,8 @@ golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= @@ -186,8 +183,8 @@ golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTF golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= -google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -197,34 +194,34 @@ 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.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.35.2 h1:tW7mWc2RpxW7HS4CoRXhtYHSzme1PN1UjGHJ1bdrtdw= -k8s.io/api v0.35.2/go.mod h1:7AJfqGoAZcwSFhOjcGM7WV05QxMMgUaChNfLTXDRE60= -k8s.io/apiextensions-apiserver v0.35.2 h1:iyStXHoJZsUXPh/nFAsjC29rjJWdSgUmG1XpApE29c0= -k8s.io/apiextensions-apiserver v0.35.2/go.mod h1:OdyGvcO1FtMDWQ+rRh/Ei3b6X3g2+ZDHd0MSRGeS8rU= -k8s.io/apimachinery v0.35.2 h1:NqsM/mmZA7sHW02JZ9RTtk3wInRgbVxL8MPfzSANAK8= -k8s.io/apimachinery v0.35.2/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= -k8s.io/apiserver v0.35.2 h1:rb52v0CZGEL0FkhjS+I6jHflAp7fZ4MIaKcEHX7wmDk= -k8s.io/apiserver v0.35.2/go.mod h1:CROJUAu0tfjZLyYgSeBsBan2T7LUJGh0ucWwTCSSk7g= -k8s.io/client-go v0.35.2 h1:YUfPefdGJA4aljDdayAXkc98DnPkIetMl4PrKX97W9o= -k8s.io/client-go v0.35.2/go.mod h1:4QqEwh4oQpeK8AaefZ0jwTFJw/9kIjdQi0jpKeYvz7g= -k8s.io/code-generator v0.35.2 h1:3874swbO2c26VWTf6lKD4NWGyHIfyBeTCk7caCG3TuU= -k8s.io/code-generator v0.35.2/go.mod h1:id4XLCm0yAQq5nlvyfAKibMOKnMjzlesAwGw6kM3Adc= -k8s.io/component-base v0.35.2 h1:btgR+qNrpWuRSuvWSnQYsZy88yf5gVwemvz0yw79pGc= -k8s.io/component-base v0.35.2/go.mod h1:B1iBJjooe6xIJYUucAxb26RwhAjzx0gHnqO9htWIX+0= -k8s.io/component-helpers v0.35.2 h1:7Ea4CDgHnyOGrl3ZhD8e46SdTyf1itTONnreJ2Q52UM= -k8s.io/component-helpers v0.35.2/go.mod h1:ybIoc8i92FG7xJFrBcEMzB8ul1wlZgfF0I4Z9w0V6VQ= +k8s.io/api v0.36.0 h1:SgqDhZzHdOtMk40xVSvCXkP9ME0H05hPM3p9AB1kL80= +k8s.io/api v0.36.0/go.mod h1:m1LVrGPNYax5NBHdO+QuAedXyuzTt4RryI/qnmNvs34= +k8s.io/apiextensions-apiserver v0.36.0 h1:Wt7E8J+VBCbj4FjiBfDTK/neXDDjyJVJc7xfuOHImZ0= +k8s.io/apiextensions-apiserver v0.36.0/go.mod h1:kGDjH0msuiIB3tgsYRV0kS9GqpMYMUsQ3GHv7TApyug= +k8s.io/apimachinery v0.36.0 h1:jZyPzhd5Z+3h9vJLt0z9XdzW9VzNzWAUw+P1xZ9PXtQ= +k8s.io/apimachinery v0.36.0/go.mod h1:FklypaRJt6n5wUIwWXIP6GJlIpUizTgfo1T/As+Tyxc= +k8s.io/apiserver v0.36.0 h1:Jg5OFAENUACByUCg15CmhZAYrr5ZyJ+jodyA1mHl3YE= +k8s.io/apiserver v0.36.0/go.mod h1:mHvwdHf+qKEm+1/hYm756SV+oREOKSPnsjagOpx6Vho= +k8s.io/client-go v0.36.0 h1:pOYi7C4RHChYjMiHpZSpSbIM6ZxVbRXBy7CuiIwqA3c= +k8s.io/client-go v0.36.0/go.mod h1:ZKKcpwF0aLYfkHFCjillCKaTK/yBkEDHTDXCFY6AS9Y= +k8s.io/code-generator v0.36.0 h1:XWAkrhnArm0VWMmSFO7kyB+wE2LROwep7hEH0GPGkqA= +k8s.io/code-generator v0.36.0/go.mod h1:Tr2UhfBRdlyRoadfob9aPCmmGe8PUs5XPK9MEJ2nx+w= +k8s.io/component-base v0.36.0 h1:hFjEktssxiJhrK1zfybkH4kJOi8iZuF+mIDCqS5+jRo= +k8s.io/component-base v0.36.0/go.mod h1:JZvIfcNHk+uck+8LhJzhSBtydWXaZNQwX2OdL+Mnwsk= +k8s.io/component-helpers v0.36.0 h1:KznLAOD7oPxjaeheW4SOQijz9UtMO8Nvp89+lR8FYks= +k8s.io/component-helpers v0.36.0/go.mod h1:BqZG+01Z97KR8GN9Stb8SiRmtn/EpZogriuQtpMCsLg= k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b h1:gMplByicHV/TJBizHd9aVEsTYoJBnnUAT5MHlTkbjhQ= k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b/go.mod h1:CgujABENc3KuTrcsdpGmrrASjtQsWCT7R99mEV4U/fM= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= +k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= k8s.io/kube-aggregator v0.35.2 h1:bnF7E238wUOVaPpTyKrqGCAEXOAJ6HRTARvJTZ0UIC0= k8s.io/kube-aggregator v0.35.2/go.mod h1:7Xl9zFJFsFIrPnwBfu7hve+G5QgLsDZRIedc8gA1mq4= -k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= -k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= -sigs.k8s.io/controller-runtime v0.23.3/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0= +k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a h1:xCeOEAOoGYl2jnJoHkC3hkbPJgdATINPMAxaynU2Ovg= +k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= +sigs.k8s.io/controller-runtime v0.24.0 h1:Ck6N2LdS8Lovy1o25BB4r1xjvLEKUl1s2o9kU+KWDE4= +sigs.k8s.io/controller-runtime v0.24.0/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw= sigs.k8s.io/jobset v0.11.1 h1:WgLEBnXTeX+4MxfVkIbfm4jIVgjvIY6Jfaei2okxKNk= sigs.k8s.io/jobset v0.11.1/go.mod h1:aPKgaoGXcxUVUQNB8RbuE7Q9pET9A9MDRsjvHO2lsH0= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= diff --git a/manifests/base/crds/trainer.kubeflow.org_clustertrainingruntimes.yaml b/manifests/base/crds/trainer.kubeflow.org_clustertrainingruntimes.yaml index b66b3f1ab6..e947075b5b 100644 --- a/manifests/base/crds/trainer.kubeflow.org_clustertrainingruntimes.yaml +++ b/manifests/base/crds/trainer.kubeflow.org_clustertrainingruntimes.yaml @@ -3037,7 +3037,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -4728,7 +4727,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -5240,7 +5238,6 @@ spec: 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. type: boolean hostname: description: |- @@ -6501,7 +6498,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -7097,6 +7093,14 @@ spec: 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. + + When the DRAWorkloadResourceClaims feature gate is enabled and this Pod + belongs to a PodGroup, a PodResourceClaim is matched to a + PodGroupResourceClaim if all of their fields are equal (Name, + ResourceClaimName, and ResourceClaimTemplateName). A matched claim references + a single ResourceClaim shared across all Pods in the PodGroup, reserved for + the PodGroup in ResourceClaimStatus.ReservedFor rather than for individual + Pods. properties: name: description: |- @@ -7122,6 +7126,16 @@ spec: generated component, will be used to form a unique name for the ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. + When the DRAWorkloadResourceClaims feature gate is enabled and the pod + belongs to a PodGroup that defines a PodGroupResourceClaim with the same + Name and ResourceClaimTemplateName, this PodResourceClaim resolves to the + ResourceClaim generated for the PodGroup. All pods in the group that + define an equivalent PodResourceClaim matching the + PodGroupResourceClaim's Name and ResourceClaimTemplateName share the same + generated ResourceClaim. ResourceClaims generated for a PodGroup are + owned by the PodGroup and their lifecycles are tied to the PodGroup + instead of any individual pod. + This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim. @@ -7249,6 +7263,28 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + schedulingGroup: + description: |- + SchedulingGroup provides a reference to the immediate scheduling runtime + grouping object that this Pod belongs to. + This field is used by the scheduler to identify the group and apply the + correct group scheduling policies. The association with a group also + impacts other lifecycle aspects of a Pod that are relevant in a wider context + of scheduling like preemption, resource attachment, etc. If not specified, + the Pod is treated as a single unit in all of these aspects. + The group object referenced by this field may not exist at the time the + Pod is created. + This field is immutable, but a group object with the same name may be + recreated with different policies. Doing this during pod scheduling + may result in the placement not conforming to the expected policies. + properties: + podGroupName: + description: |- + PodGroupName specifies the name of the standalone PodGroup object + that represents the runtime instance of this group. + Must be a DNS subdomain. + type: string + type: object securityContext: description: |- SecurityContext holds pod-level security attributes and common container settings. @@ -8773,7 +8809,7 @@ spec: A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. - The volume will be mounted read-only (ro) and non-executable files (noexec). + The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: @@ -8951,8 +8987,7 @@ spec: description: |- portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type - are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate - is on. + are redirected to the pxd.portworx.com CSI driver. properties: fsType: description: |- @@ -9872,42 +9907,6 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map - workloadRef: - description: |- - WorkloadRef provides a reference to the Workload object that this Pod belongs to. - This field is used by the scheduler to identify the PodGroup and apply the - correct group scheduling policies. The Workload object referenced - by this field may not exist at the time the Pod is created. - This field is immutable, but a Workload object with the same name - may be recreated with different policies. Doing this during pod scheduling - may result in the placement not conforming to the expected policies. - properties: - name: - description: |- - Name defines the name of the Workload object this Pod belongs to. - Workload must be in the same namespace as the Pod. - If it doesn't match any existing Workload, the Pod will remain unschedulable - until a Workload object is created and observed by the kube-scheduler. - It must be a DNS subdomain. - type: string - podGroup: - description: |- - PodGroup is the name of the PodGroup within the Workload that this Pod - belongs to. If it doesn't match any existing PodGroup within the Workload, - the Pod will remain unschedulable until the Workload object is recreated - and observed by the kube-scheduler. It must be a DNS label. - type: string - podGroupReplicaKey: - description: |- - PodGroupReplicaKey specifies the replica key of the PodGroup to which this - Pod belongs. It is used to distinguish pods belonging to different replicas - of the same pod group. The pod group policy is applied separately to each replica. - When set, it must be a DNS label. - type: string - required: - - name - - podGroup - type: object required: - containers type: object diff --git a/manifests/base/crds/trainer.kubeflow.org_trainingruntimes.yaml b/manifests/base/crds/trainer.kubeflow.org_trainingruntimes.yaml index 08cf086562..cf2d0654ff 100644 --- a/manifests/base/crds/trainer.kubeflow.org_trainingruntimes.yaml +++ b/manifests/base/crds/trainer.kubeflow.org_trainingruntimes.yaml @@ -3037,7 +3037,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -4728,7 +4727,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -5240,7 +5238,6 @@ spec: 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. type: boolean hostname: description: |- @@ -6501,7 +6498,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -7097,6 +7093,14 @@ spec: 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. + + When the DRAWorkloadResourceClaims feature gate is enabled and this Pod + belongs to a PodGroup, a PodResourceClaim is matched to a + PodGroupResourceClaim if all of their fields are equal (Name, + ResourceClaimName, and ResourceClaimTemplateName). A matched claim references + a single ResourceClaim shared across all Pods in the PodGroup, reserved for + the PodGroup in ResourceClaimStatus.ReservedFor rather than for individual + Pods. properties: name: description: |- @@ -7122,6 +7126,16 @@ spec: generated component, will be used to form a unique name for the ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. + When the DRAWorkloadResourceClaims feature gate is enabled and the pod + belongs to a PodGroup that defines a PodGroupResourceClaim with the same + Name and ResourceClaimTemplateName, this PodResourceClaim resolves to the + ResourceClaim generated for the PodGroup. All pods in the group that + define an equivalent PodResourceClaim matching the + PodGroupResourceClaim's Name and ResourceClaimTemplateName share the same + generated ResourceClaim. ResourceClaims generated for a PodGroup are + owned by the PodGroup and their lifecycles are tied to the PodGroup + instead of any individual pod. + This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim. @@ -7249,6 +7263,28 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + schedulingGroup: + description: |- + SchedulingGroup provides a reference to the immediate scheduling runtime + grouping object that this Pod belongs to. + This field is used by the scheduler to identify the group and apply the + correct group scheduling policies. The association with a group also + impacts other lifecycle aspects of a Pod that are relevant in a wider context + of scheduling like preemption, resource attachment, etc. If not specified, + the Pod is treated as a single unit in all of these aspects. + The group object referenced by this field may not exist at the time the + Pod is created. + This field is immutable, but a group object with the same name may be + recreated with different policies. Doing this during pod scheduling + may result in the placement not conforming to the expected policies. + properties: + podGroupName: + description: |- + PodGroupName specifies the name of the standalone PodGroup object + that represents the runtime instance of this group. + Must be a DNS subdomain. + type: string + type: object securityContext: description: |- SecurityContext holds pod-level security attributes and common container settings. @@ -8773,7 +8809,7 @@ spec: A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. - The volume will be mounted read-only (ro) and non-executable files (noexec). + The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: @@ -8951,8 +8987,7 @@ spec: description: |- portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type - are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate - is on. + are redirected to the pxd.portworx.com CSI driver. properties: fsType: description: |- @@ -9872,42 +9907,6 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map - workloadRef: - description: |- - WorkloadRef provides a reference to the Workload object that this Pod belongs to. - This field is used by the scheduler to identify the PodGroup and apply the - correct group scheduling policies. The Workload object referenced - by this field may not exist at the time the Pod is created. - This field is immutable, but a Workload object with the same name - may be recreated with different policies. Doing this during pod scheduling - may result in the placement not conforming to the expected policies. - properties: - name: - description: |- - Name defines the name of the Workload object this Pod belongs to. - Workload must be in the same namespace as the Pod. - If it doesn't match any existing Workload, the Pod will remain unschedulable - until a Workload object is created and observed by the kube-scheduler. - It must be a DNS subdomain. - type: string - podGroup: - description: |- - PodGroup is the name of the PodGroup within the Workload that this Pod - belongs to. If it doesn't match any existing PodGroup within the Workload, - the Pod will remain unschedulable until the Workload object is recreated - and observed by the kube-scheduler. It must be a DNS label. - type: string - podGroupReplicaKey: - description: |- - PodGroupReplicaKey specifies the replica key of the PodGroup to which this - Pod belongs. It is used to distinguish pods belonging to different replicas - of the same pod group. The pod group policy is applied separately to each replica. - When set, it must be a DNS label. - type: string - required: - - name - - podGroup - type: object required: - containers type: object diff --git a/manifests/base/crds/trainer.kubeflow.org_trainjobs.yaml b/manifests/base/crds/trainer.kubeflow.org_trainjobs.yaml index acac158aa8..a4418a0b52 100644 --- a/manifests/base/crds/trainer.kubeflow.org_trainjobs.yaml +++ b/manifests/base/crds/trainer.kubeflow.org_trainjobs.yaml @@ -2038,7 +2038,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -2621,7 +2620,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -4283,7 +4281,7 @@ spec: A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. - The volume will be mounted read-only (ro) and non-executable files (noexec). + The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: @@ -4471,8 +4469,7 @@ spec: description: |- portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type - are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate - is on. + are redirected to the pxd.portworx.com CSI driver. properties: fsType: description: |- diff --git a/pkg/apis/config/v1alpha1/doc.go b/pkg/apis/config/v1alpha1/doc.go new file mode 100644 index 0000000000..9c5bcc4606 --- /dev/null +++ b/pkg/apis/config/v1alpha1/doc.go @@ -0,0 +1,19 @@ +// Copyright The Kubeflow 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:defaulter-gen=TypeMeta + +// Package v1alpha1 contains the v1alpha1 API of the Kubeflow Trainer controller manager configuration. +// +groupName=config.trainer.kubeflow.org +package v1alpha1 diff --git a/pkg/apis/trainer/v1alpha1/groupversion_info.go b/pkg/apis/trainer/v1alpha1/groupversion_info.go index edd602170a..e7c9b7520d 100644 --- a/pkg/apis/trainer/v1alpha1/groupversion_info.go +++ b/pkg/apis/trainer/v1alpha1/groupversion_info.go @@ -20,8 +20,9 @@ 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" - "sigs.k8s.io/controller-runtime/pkg/scheme" ) var ( @@ -29,7 +30,7 @@ var ( GroupVersion = schema.GroupVersion{Group: "trainer.kubeflow.org", Version: "v1alpha1"} // SchemeBuilder is used to add go types to the GroupVersionKind scheme. - SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) // SchemeGroupVersion is alias to GroupVersion for client-go libraries. SchemeGroupVersion = GroupVersion @@ -38,6 +39,19 @@ var ( AddToScheme = SchemeBuilder.AddToScheme ) +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(GroupVersion, + &TrainJob{}, + &TrainJobList{}, + &ClusterTrainingRuntime{}, + &ClusterTrainingRuntimeList{}, + &TrainingRuntime{}, + &TrainingRuntimeList{}, + ) + metav1.AddToGroupVersion(scheme, GroupVersion) + return nil +} + // Resource takes an unqualified resource and returns a Group-qualified GroupResource. func Resource(resource string) schema.GroupResource { return GroupVersion.WithResource(resource).GroupResource() diff --git a/pkg/apis/trainer/v1alpha1/trainingruntime_types.go b/pkg/apis/trainer/v1alpha1/trainingruntime_types.go index 04c9f728f7..7e76e22308 100644 --- a/pkg/apis/trainer/v1alpha1/trainingruntime_types.go +++ b/pkg/apis/trainer/v1alpha1/trainingruntime_types.go @@ -267,7 +267,3 @@ const ( MPIImplementationIntel MPIImplementation = "Intel" MPIImplementationMPICH MPIImplementation = "MPICH" ) - -func init() { - SchemeBuilder.Register(&ClusterTrainingRuntime{}, &ClusterTrainingRuntimeList{}, &TrainingRuntime{}, &TrainingRuntimeList{}) -} diff --git a/pkg/apis/trainer/v1alpha1/trainjob_types.go b/pkg/apis/trainer/v1alpha1/trainjob_types.go index 86e378c7e3..6c5d51a84e 100644 --- a/pkg/apis/trainer/v1alpha1/trainjob_types.go +++ b/pkg/apis/trainer/v1alpha1/trainjob_types.go @@ -606,7 +606,3 @@ type UpdateTrainJobStatusRequest struct { // +optional TrainerStatus *TrainerStatus `json:"trainerStatus,omitempty"` } - -func init() { - SchemeBuilder.Register(&TrainJob{}, &TrainJobList{}) -} diff --git a/pkg/apis/trainer/v1alpha1/zz_generated.openapi.go b/pkg/apis/trainer/v1alpha1/zz_generated.openapi.go index b79bfb5b23..9833b0a19d 100644 --- a/pkg/apis/trainer/v1alpha1/zz_generated.openapi.go +++ b/pkg/apis/trainer/v1alpha1/zz_generated.openapi.go @@ -194,6 +194,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA corev1.ISCSIPersistentVolumeSource{}.OpenAPIModelName(): schema_k8sio_api_core_v1_ISCSIPersistentVolumeSource(ref), corev1.ISCSIVolumeSource{}.OpenAPIModelName(): schema_k8sio_api_core_v1_ISCSIVolumeSource(ref), corev1.ImageVolumeSource{}.OpenAPIModelName(): schema_k8sio_api_core_v1_ImageVolumeSource(ref), + corev1.ImageVolumeStatus{}.OpenAPIModelName(): schema_k8sio_api_core_v1_ImageVolumeStatus(ref), corev1.KeyToPath{}.OpenAPIModelName(): schema_k8sio_api_core_v1_KeyToPath(ref), corev1.Lifecycle{}.OpenAPIModelName(): schema_k8sio_api_core_v1_Lifecycle(ref), corev1.LifecycleHandler{}.OpenAPIModelName(): schema_k8sio_api_core_v1_LifecycleHandler(ref), @@ -217,6 +218,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA corev1.Node{}.OpenAPIModelName(): schema_k8sio_api_core_v1_Node(ref), corev1.NodeAddress{}.OpenAPIModelName(): schema_k8sio_api_core_v1_NodeAddress(ref), corev1.NodeAffinity{}.OpenAPIModelName(): schema_k8sio_api_core_v1_NodeAffinity(ref), + corev1.NodeAllocatableResourceClaimStatus{}.OpenAPIModelName(): schema_k8sio_api_core_v1_NodeAllocatableResourceClaimStatus(ref), corev1.NodeCondition{}.OpenAPIModelName(): schema_k8sio_api_core_v1_NodeCondition(ref), corev1.NodeConfigSource{}.OpenAPIModelName(): schema_k8sio_api_core_v1_NodeConfigSource(ref), corev1.NodeConfigStatus{}.OpenAPIModelName(): schema_k8sio_api_core_v1_NodeConfigStatus(ref), @@ -269,6 +271,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA corev1.PodResourceClaim{}.OpenAPIModelName(): schema_k8sio_api_core_v1_PodResourceClaim(ref), corev1.PodResourceClaimStatus{}.OpenAPIModelName(): schema_k8sio_api_core_v1_PodResourceClaimStatus(ref), corev1.PodSchedulingGate{}.OpenAPIModelName(): schema_k8sio_api_core_v1_PodSchedulingGate(ref), + corev1.PodSchedulingGroup{}.OpenAPIModelName(): schema_k8sio_api_core_v1_PodSchedulingGroup(ref), corev1.PodSecurityContext{}.OpenAPIModelName(): schema_k8sio_api_core_v1_PodSecurityContext(ref), corev1.PodSignature{}.OpenAPIModelName(): schema_k8sio_api_core_v1_PodSignature(ref), corev1.PodSpec{}.OpenAPIModelName(): schema_k8sio_api_core_v1_PodSpec(ref), @@ -347,10 +350,10 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA corev1.VolumeProjection{}.OpenAPIModelName(): schema_k8sio_api_core_v1_VolumeProjection(ref), corev1.VolumeResourceRequirements{}.OpenAPIModelName(): schema_k8sio_api_core_v1_VolumeResourceRequirements(ref), corev1.VolumeSource{}.OpenAPIModelName(): schema_k8sio_api_core_v1_VolumeSource(ref), + corev1.VolumeStatus{}.OpenAPIModelName(): schema_k8sio_api_core_v1_VolumeStatus(ref), corev1.VsphereVirtualDiskVolumeSource{}.OpenAPIModelName(): schema_k8sio_api_core_v1_VsphereVirtualDiskVolumeSource(ref), corev1.WeightedPodAffinityTerm{}.OpenAPIModelName(): schema_k8sio_api_core_v1_WeightedPodAffinityTerm(ref), corev1.WindowsSecurityContextOptions{}.OpenAPIModelName(): schema_k8sio_api_core_v1_WindowsSecurityContextOptions(ref), - corev1.WorkloadReference{}.OpenAPIModelName(): schema_k8sio_api_core_v1_WorkloadReference(ref), resource.Quantity{}.OpenAPIModelName(): schema_apimachinery_pkg_api_resource_Quantity(ref), metav1.APIGroup{}.OpenAPIModelName(): schema_pkg_apis_meta_v1_APIGroup(ref), metav1.APIGroupList{}.OpenAPIModelName(): schema_pkg_apis_meta_v1_APIGroupList(ref), @@ -388,6 +391,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA metav1.Preconditions{}.OpenAPIModelName(): schema_pkg_apis_meta_v1_Preconditions(ref), metav1.RootPaths{}.OpenAPIModelName(): schema_pkg_apis_meta_v1_RootPaths(ref), metav1.ServerAddressByClientCIDR{}.OpenAPIModelName(): schema_pkg_apis_meta_v1_ServerAddressByClientCIDR(ref), + metav1.ShardInfo{}.OpenAPIModelName(): schema_pkg_apis_meta_v1_ShardInfo(ref), metav1.Status{}.OpenAPIModelName(): schema_pkg_apis_meta_v1_Status(ref), metav1.StatusCause{}.OpenAPIModelName(): schema_pkg_apis_meta_v1_StatusCause(ref), metav1.StatusDetails{}.OpenAPIModelName(): schema_pkg_apis_meta_v1_StatusDetails(ref), @@ -2429,6 +2433,7 @@ func schema_k8sio_api_autoscaling_v2_HorizontalPodAutoscaler(ref common.Referenc }, }, }, + Required: []string{"spec"}, }, }, Dependencies: []string{ @@ -3170,6 +3175,7 @@ func schema_k8sio_api_batch_v1_CronJob(ref common.ReferenceCallback) common.Open }, }, }, + Required: []string{"spec"}, }, }, Dependencies: []string{ @@ -8704,6 +8710,27 @@ func schema_k8sio_api_core_v1_ImageVolumeSource(ref common.ReferenceCallback) co } } +func schema_k8sio_api_core_v1_ImageVolumeStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ImageVolumeStatus represents the image-based volume status.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "imageRef": { + SchemaProps: spec.SchemaProps{ + Description: "ImageRef is the digest of the image used for this volume. It should have a value that's similar to the pod's status.containerStatuses[i].imageID. The ImageRef length should not exceed 256 characters.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"imageRef"}, + }, + }, + } +} + func schema_k8sio_api_core_v1_KeyToPath(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -9702,6 +9729,64 @@ func schema_k8sio_api_core_v1_NodeAffinity(ref common.ReferenceCallback) common. } } +func schema_k8sio_api_core_v1_NodeAllocatableResourceClaimStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "NodeAllocatableResourceClaimStatus describes the status of node allocatable resources allocated via DRA.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "resourceClaimName": { + SchemaProps: spec.SchemaProps{ + Description: "ResourceClaimName is the resource claim referenced by the pod that resulted in this node allocatable resource allocation.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "containers": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "set", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "Containers lists the names of all containers in this pod that reference the claim.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "resources": { + SchemaProps: spec.SchemaProps{ + Description: "Resources is a map of the node-allocatable resource name to the aggregate quantity allocated to the claim.", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref(resource.Quantity{}.OpenAPIModelName()), + }, + }, + }, + }, + }, + }, + Required: []string{"resourceClaimName", "resources"}, + }, + }, + Dependencies: []string{ + resource.Quantity{}.OpenAPIModelName()}, + } +} + func schema_k8sio_api_core_v1_NodeCondition(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -11338,7 +11423,7 @@ func schema_k8sio_api_core_v1_PersistentVolumeSource(ref common.ReferenceCallbac }, "portworxVolume": { SchemaProps: spec.SchemaProps{ - Description: "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on.", + Description: "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver.", Ref: ref(corev1.PortworxVolumeSource{}.OpenAPIModelName()), }, }, @@ -11499,7 +11584,7 @@ func schema_k8sio_api_core_v1_PersistentVolumeSpec(ref common.ReferenceCallback) }, "portworxVolume": { SchemaProps: spec.SchemaProps{ - Description: "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on.", + Description: "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver.", Ref: ref(corev1.PortworxVolumeSource{}.OpenAPIModelName()), }, }, @@ -12098,7 +12183,7 @@ func schema_k8sio_api_core_v1_PodCondition(ref common.ReferenceCallback) common. }, "observedGeneration": { SchemaProps: spec.SchemaProps{ - Description: "If set, this represents the .metadata.generation that the pod condition was set based upon. The PodObservedGenerationTracking feature gate must be enabled to use this field.", + Description: "If set, this represents the .metadata.generation that the pod condition was set based upon.", Type: []string{"integer"}, Format: "int64", }, @@ -12673,7 +12758,7 @@ func schema_k8sio_api_core_v1_PodResourceClaim(ref common.ReferenceCallback) com return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "PodResourceClaim references exactly one ResourceClaim, either directly or by naming a ResourceClaimTemplate which is then turned into a ResourceClaim for the pod.\n\nIt 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.", + Description: "PodResourceClaim references exactly one ResourceClaim, either directly or by naming a ResourceClaimTemplate which is then turned into a ResourceClaim for the pod.\n\nIt 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.\n\nWhen the DRAWorkloadResourceClaims feature gate is enabled and this Pod belongs to a PodGroup, a PodResourceClaim is matched to a PodGroupResourceClaim if all of their fields are equal (Name, ResourceClaimName, and ResourceClaimTemplateName). A matched claim references a single ResourceClaim shared across all Pods in the PodGroup, reserved for the PodGroup in ResourceClaimStatus.ReservedFor rather than for individual Pods.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "name": { @@ -12693,7 +12778,7 @@ func schema_k8sio_api_core_v1_PodResourceClaim(ref common.ReferenceCallback) com }, "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 pod name and resource name, along with a generated component, will be used to form a unique name for the ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses.\n\nThis field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim.\n\nExactly one of ResourceClaimName and ResourceClaimTemplateName must be set.", + 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 pod name and resource name, along with a generated component, will be used to form a unique name for the ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses.\n\nWhen the DRAWorkloadResourceClaims feature gate is enabled and the pod belongs to a PodGroup that defines a PodGroupResourceClaim with the same Name and ResourceClaimTemplateName, this PodResourceClaim resolves to the ResourceClaim generated for the PodGroup. All pods in the group that define an equivalent PodResourceClaim matching the PodGroupResourceClaim's Name and ResourceClaimTemplateName share the same generated ResourceClaim. ResourceClaims generated for a PodGroup are owned by the PodGroup and their lifecycles are tied to the PodGroup instead of any individual pod.\n\nThis field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim.\n\nExactly one of ResourceClaimName and ResourceClaimTemplateName must be set.", Type: []string{"string"}, Format: "", }, @@ -12722,7 +12807,7 @@ func schema_k8sio_api_core_v1_PodResourceClaimStatus(ref common.ReferenceCallbac }, "resourceClaimName": { SchemaProps: spec.SchemaProps{ - Description: "ResourceClaimName is the name of the ResourceClaim that was generated for the Pod in the namespace of the Pod. If this is unset, then generating a ResourceClaim was not necessary. The pod.spec.resourceClaims entry can be ignored in this case.", + Description: "ResourceClaimName is the name of the ResourceClaim that was generated for the Pod in the namespace of the Pod.\n\nWhen the DRAWorkloadResourceClaims feature is enabled and the corresponding PodResourceClaim matches a PodGroupResourceClaim made by the Pod's PodGroup, then this is the name of the ResourceClaim generated and reserved for the PodGroup.\n\nIf this is unset, then generating a ResourceClaim was not necessary. The pod.spec.resourceClaims entry can be ignored in this case.", Type: []string{"string"}, Format: "", }, @@ -12756,6 +12841,37 @@ func schema_k8sio_api_core_v1_PodSchedulingGate(ref common.ReferenceCallback) co } } +func schema_k8sio_api_core_v1_PodSchedulingGroup(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "PodSchedulingGroup identifies the runtime scheduling group instance that a Pod belongs to. The scheduler uses this information to apply workload-aware scheduling semantics. Exactly one field must be specified.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "podGroupName": { + SchemaProps: spec.SchemaProps{ + Description: "PodGroupName specifies the name of the standalone PodGroup object that represents the runtime instance of this group. Must be a DNS subdomain.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-unions": []interface{}{ + map[string]interface{}{ + "fields-to-discriminateBy": map[string]interface{}{ + "podGroupName": "PodGroupName", + }, + }, + }, + }, + }, + }, + } +} + func schema_k8sio_api_core_v1_PodSecurityContext(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -13331,7 +13447,7 @@ func schema_k8sio_api_core_v1_PodSpec(ref common.ReferenceCallback) common.OpenA }, "hostUsers": { SchemaProps: spec.SchemaProps{ - Description: "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.", + Description: "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.", Type: []string{"boolean"}, Format: "", }, @@ -13397,10 +13513,10 @@ func schema_k8sio_api_core_v1_PodSpec(ref common.ReferenceCallback) common.OpenA Format: "", }, }, - "workloadRef": { + "schedulingGroup": { SchemaProps: spec.SchemaProps{ - Description: "WorkloadRef provides a reference to the Workload object that this Pod belongs to. This field is used by the scheduler to identify the PodGroup and apply the correct group scheduling policies. The Workload object referenced by this field may not exist at the time the Pod is created. This field is immutable, but a Workload object with the same name may be recreated with different policies. Doing this during pod scheduling may result in the placement not conforming to the expected policies.", - Ref: ref(corev1.WorkloadReference{}.OpenAPIModelName()), + Description: "SchedulingGroup provides a reference to the immediate scheduling runtime grouping object that this Pod belongs to. This field is used by the scheduler to identify the group and apply the correct group scheduling policies. The association with a group also impacts other lifecycle aspects of a Pod that are relevant in a wider context of scheduling like preemption, resource attachment, etc. If not specified, the Pod is treated as a single unit in all of these aspects. The group object referenced by this field may not exist at the time the Pod is created. This field is immutable, but a group object with the same name may be recreated with different policies. Doing this during pod scheduling may result in the placement not conforming to the expected policies.", + Ref: ref(corev1.PodSchedulingGroup{}.OpenAPIModelName()), }, }, }, @@ -13408,7 +13524,7 @@ func schema_k8sio_api_core_v1_PodSpec(ref common.ReferenceCallback) common.OpenA }, }, Dependencies: []string{ - corev1.Affinity{}.OpenAPIModelName(), corev1.Container{}.OpenAPIModelName(), corev1.EphemeralContainer{}.OpenAPIModelName(), corev1.HostAlias{}.OpenAPIModelName(), corev1.LocalObjectReference{}.OpenAPIModelName(), corev1.PodDNSConfig{}.OpenAPIModelName(), corev1.PodOS{}.OpenAPIModelName(), corev1.PodReadinessGate{}.OpenAPIModelName(), corev1.PodResourceClaim{}.OpenAPIModelName(), corev1.PodSchedulingGate{}.OpenAPIModelName(), corev1.PodSecurityContext{}.OpenAPIModelName(), corev1.ResourceRequirements{}.OpenAPIModelName(), corev1.Toleration{}.OpenAPIModelName(), corev1.TopologySpreadConstraint{}.OpenAPIModelName(), corev1.Volume{}.OpenAPIModelName(), corev1.WorkloadReference{}.OpenAPIModelName(), resource.Quantity{}.OpenAPIModelName()}, + corev1.Affinity{}.OpenAPIModelName(), corev1.Container{}.OpenAPIModelName(), corev1.EphemeralContainer{}.OpenAPIModelName(), corev1.HostAlias{}.OpenAPIModelName(), corev1.LocalObjectReference{}.OpenAPIModelName(), corev1.PodDNSConfig{}.OpenAPIModelName(), corev1.PodOS{}.OpenAPIModelName(), corev1.PodReadinessGate{}.OpenAPIModelName(), corev1.PodResourceClaim{}.OpenAPIModelName(), corev1.PodSchedulingGate{}.OpenAPIModelName(), corev1.PodSchedulingGroup{}.OpenAPIModelName(), corev1.PodSecurityContext{}.OpenAPIModelName(), corev1.ResourceRequirements{}.OpenAPIModelName(), corev1.Toleration{}.OpenAPIModelName(), corev1.TopologySpreadConstraint{}.OpenAPIModelName(), corev1.Volume{}.OpenAPIModelName(), resource.Quantity{}.OpenAPIModelName()}, } } @@ -13666,11 +13782,30 @@ func schema_k8sio_api_core_v1_PodStatus(ref common.ReferenceCallback) common.Ope Ref: ref(corev1.ResourceRequirements{}.OpenAPIModelName()), }, }, + "nodeAllocatableResourceClaimStatuses": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "NodeAllocatableResourceClaimStatuses contains the status of node-allocatable resources that were allocated for this pod through DRA claims. This includes resources currently reported in v1.Node `status.allocatable` that are not extended resources (see https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#extended-resources). Examples include \"cpu\", \"memory\", \"ephemeral-storage\", and hugepages.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref(corev1.NodeAllocatableResourceClaimStatus{}.OpenAPIModelName()), + }, + }, + }, + }, + }, }, }, }, Dependencies: []string{ - corev1.ContainerStatus{}.OpenAPIModelName(), corev1.HostIP{}.OpenAPIModelName(), corev1.PodCondition{}.OpenAPIModelName(), corev1.PodExtendedResourceClaimStatus{}.OpenAPIModelName(), corev1.PodIP{}.OpenAPIModelName(), corev1.PodResourceClaimStatus{}.OpenAPIModelName(), corev1.ResourceRequirements{}.OpenAPIModelName(), resource.Quantity{}.OpenAPIModelName(), metav1.Time{}.OpenAPIModelName()}, + corev1.ContainerStatus{}.OpenAPIModelName(), corev1.HostIP{}.OpenAPIModelName(), corev1.NodeAllocatableResourceClaimStatus{}.OpenAPIModelName(), corev1.PodCondition{}.OpenAPIModelName(), corev1.PodExtendedResourceClaimStatus{}.OpenAPIModelName(), corev1.PodIP{}.OpenAPIModelName(), corev1.PodResourceClaimStatus{}.OpenAPIModelName(), corev1.ResourceRequirements{}.OpenAPIModelName(), resource.Quantity{}.OpenAPIModelName(), metav1.Time{}.OpenAPIModelName()}, } } @@ -14815,6 +14950,13 @@ func schema_k8sio_api_core_v1_ResourceHealth(ref common.ReferenceCallback) commo Format: "", }, }, + "message": { + SchemaProps: spec.SchemaProps{ + Description: "Message provides human-readable context for Health (e.g. \"ECC error count exceeded threshold\"). This field is populated by the kubelet when ResourceHealthStatusMessage is enabled if the DRA plugin returns a message, and is null otherwise.", + Type: []string{"string"}, + Format: "", + }, + }, }, Required: []string{"resourceID"}, }, @@ -15892,7 +16034,7 @@ func schema_k8sio_api_core_v1_SecurityContext(ref common.ReferenceCallback) comm }, "procMount": { SchemaProps: spec.SchemaProps{ - Description: "procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows.\n\nPossible enum values:\n - `\"Default\"` uses the container runtime defaults for readonly and masked paths for /proc. Most container runtimes mask certain paths in /proc to avoid accidental security exposure of special devices or information.\n - `\"Unmasked\"` bypasses the default masking behavior of the container runtime and ensures the newly created /proc the container stays in tact with no modifications.", + Description: "procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. Note that this field cannot be set when spec.os.name is windows.\n\nPossible enum values:\n - `\"Default\"` uses the container runtime defaults for readonly and masked paths for /proc. Most container runtimes mask certain paths in /proc to avoid accidental security exposure of special devices or information.\n - `\"Unmasked\"` bypasses the default masking behavior of the container runtime and ensures the newly created /proc the container stays in tact with no modifications.", Type: []string{"string"}, Format: "", Enum: []interface{}{"Default", "Unmasked"}, @@ -17326,7 +17468,7 @@ func schema_k8sio_api_core_v1_Volume(ref common.ReferenceCallback) common.OpenAP }, "portworxVolume": { SchemaProps: spec.SchemaProps{ - Description: "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on.", + Description: "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver.", Ref: ref(corev1.PortworxVolumeSource{}.OpenAPIModelName()), }, }, @@ -17356,7 +17498,7 @@ func schema_k8sio_api_core_v1_Volume(ref common.ReferenceCallback) common.OpenAP }, "image": { SchemaProps: spec.SchemaProps{ - Description: "image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided:\n\n- Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails.\n\nThe volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.", + Description: "image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided:\n\n- Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails.\n\nThe volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.", Ref: ref(corev1.ImageVolumeSource{}.OpenAPIModelName()), }, }, @@ -17502,10 +17644,18 @@ func schema_k8sio_api_core_v1_VolumeMountStatus(ref common.ReferenceCallback) co Format: "", }, }, + "volumeStatus": { + SchemaProps: spec.SchemaProps{ + Description: "volumeStatus represents volume-type-specific status about the mounted volume.", + Ref: ref(corev1.VolumeStatus{}.OpenAPIModelName()), + }, + }, }, Required: []string{"name", "mountPath"}, }, }, + Dependencies: []string{ + corev1.VolumeStatus{}.OpenAPIModelName()}, } } @@ -17777,7 +17927,7 @@ func schema_k8sio_api_core_v1_VolumeSource(ref common.ReferenceCallback) common. }, "portworxVolume": { SchemaProps: spec.SchemaProps{ - Description: "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate is on.", + Description: "portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type are redirected to the pxd.portworx.com CSI driver.", Ref: ref(corev1.PortworxVolumeSource{}.OpenAPIModelName()), }, }, @@ -17807,7 +17957,7 @@ func schema_k8sio_api_core_v1_VolumeSource(ref common.ReferenceCallback) common. }, "image": { SchemaProps: spec.SchemaProps{ - Description: "image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided:\n\n- Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails.\n\nThe volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.", + Description: "image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. The volume is resolved at pod startup depending on which PullPolicy value is provided:\n\n- Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails.\n\nThe volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type.", Ref: ref(corev1.ImageVolumeSource{}.OpenAPIModelName()), }, }, @@ -17819,6 +17969,27 @@ func schema_k8sio_api_core_v1_VolumeSource(ref common.ReferenceCallback) common. } } +func schema_k8sio_api_core_v1_VolumeStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VolumeStatus represents the status of a mounted volume. At most one of its members must be specified.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "image": { + SchemaProps: spec.SchemaProps{ + Description: "image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine.", + Ref: ref(corev1.ImageVolumeStatus{}.OpenAPIModelName()), + }, + }, + }, + }, + }, + Dependencies: []string{ + corev1.ImageVolumeStatus{}.OpenAPIModelName()}, + } +} + func schema_k8sio_api_core_v1_VsphereVirtualDiskVolumeSource(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -17934,43 +18105,6 @@ func schema_k8sio_api_core_v1_WindowsSecurityContextOptions(ref common.Reference } } -func schema_k8sio_api_core_v1_WorkloadReference(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "WorkloadReference identifies the Workload object and PodGroup membership that a Pod belongs to. The scheduler uses this information to apply workload-aware scheduling semantics.", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "name": { - SchemaProps: spec.SchemaProps{ - Description: "Name defines the name of the Workload object this Pod belongs to. Workload must be in the same namespace as the Pod. If it doesn't match any existing Workload, the Pod will remain unschedulable until a Workload object is created and observed by the kube-scheduler. It must be a DNS subdomain.", - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "podGroup": { - SchemaProps: spec.SchemaProps{ - Description: "PodGroup is the name of the PodGroup within the Workload that this Pod belongs to. If it doesn't match any existing PodGroup within the Workload, the Pod will remain unschedulable until the Workload object is recreated and observed by the kube-scheduler. It must be a DNS label.", - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "podGroupReplicaKey": { - SchemaProps: spec.SchemaProps{ - Description: "PodGroupReplicaKey specifies the replica key of the PodGroup to which this Pod belongs. It is used to distinguish pods belonging to different replicas of the same pod group. The pod group policy is applied separately to each replica. When set, it must be a DNS label.", - Type: []string{"string"}, - Format: "", - }, - }, - }, - Required: []string{"name", "podGroup"}, - }, - }, - } -} - func schema_apimachinery_pkg_api_resource_Quantity(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.EmbedOpenAPIDefinitionIntoV2Extension(common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -19175,9 +19309,17 @@ func schema_pkg_apis_meta_v1_ListMeta(ref common.ReferenceCallback) common.OpenA Format: "int64", }, }, + "shardInfo": { + SchemaProps: spec.SchemaProps{ + Description: "shardInfo is set when the list is a filtered subset of the full collection, as selected by a shard selector on the request. It echoes back the selector so clients can verify which shard they received and merge sharded responses. Clients should not cache sharded list responses as a full representation of the collection.\n\nThis is an alpha field and requires enabling the ShardedListAndWatch feature gate.", + Ref: ref(metav1.ShardInfo{}.OpenAPIModelName()), + }, + }, }, }, }, + Dependencies: []string{ + metav1.ShardInfo{}.OpenAPIModelName()}, } } @@ -19272,6 +19414,13 @@ func schema_pkg_apis_meta_v1_ListOptions(ref common.ReferenceCallback) common.Op Format: "", }, }, + "shardSelector": { + SchemaProps: spec.SchemaProps{ + Description: "shardSelector restricts the list of returned objects using a CEL-based shard selector expression. The format uses the shardRange() function combined with || (logical OR) to specify one or more hash ranges:\n\n shardRange(object.metadata.uid, '0x0', '0x8000000000000000')\n shardRange(object.metadata.uid, '0x0', '0x8000000000000000') || shardRange(object.metadata.uid, '0x8000000000000000', '0x10000000000000000')\n\nField paths use CEL-style object-rooted syntax (e.g. \"object.metadata.uid\"), NOT the fieldSelector format (\"metadata.uid\"). Currently supported paths:\n - object.metadata.uid\n - object.metadata.namespace\n\nhexStart and hexEnd are single-quoted CEL string literals with a '0x' prefix, defining the inclusive lower and exclusive upper bounds over the 64-bit FNV-1a hash space. The full range is [0x0, 0x10000000000000000), where the exclusive upper bound equals 2^64.\n\nExamples:\n 2-shard split:\n shard 0: shardRange(object.metadata.uid, '0x0000000000000000', '0x8000000000000000')\n shard 1: shardRange(object.metadata.uid, '0x8000000000000000', '0x10000000000000000')\n 4-shard split:\n shard 0: shardRange(object.metadata.uid, '0x0000000000000000', '0x4000000000000000')\n shard 1: shardRange(object.metadata.uid, '0x4000000000000000', '0x8000000000000000')\n shard 2: shardRange(object.metadata.uid, '0x8000000000000000', '0xc000000000000000')\n shard 3: shardRange(object.metadata.uid, '0xc000000000000000', '0x10000000000000000')\n\nThis is an alpha field and requires enabling the ShardedListAndWatch feature gate.", + Type: []string{"string"}, + Format: "", + }, + }, }, }, }, @@ -19853,6 +20002,28 @@ func schema_pkg_apis_meta_v1_ServerAddressByClientCIDR(ref common.ReferenceCallb } } +func schema_pkg_apis_meta_v1_ShardInfo(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ShardInfo describes the shard selector that was applied to produce a list response. Its presence on a list response indicates the list is a filtered subset.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "selector": { + SchemaProps: spec.SchemaProps{ + Description: "selector is the shard selector string from the request, echoed back so clients can verify which shard they received and merge responses from multiple shards.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"selector"}, + }, + }, + } +} + func schema_pkg_apis_meta_v1_Status(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index dca209d78c..3a08d98c09 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -33,10 +33,6 @@ import ( // It's backed by a very simple object tracker that processes creates, updates and deletions as-is, // without applying any field management, validations and/or defaults. It shouldn't be considered a replacement // for a real clientset and is mostly useful in simple unit tests. -// -// Deprecated: NewClientset replaces this with support for field management, which significantly improves -// server side apply testing. NewClientset is only available when apply configurations are generated (e.g. -// via --with-applyconfig). func NewSimpleClientset(objects ...runtime.Object) *Clientset { o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) for _, obj := range objects { @@ -82,7 +78,7 @@ func (c *Clientset) Tracker() testing.ObjectTracker { return c.tracker } -// IsWatchListSemanticsSupported informs the reflector that this client +// IsWatchListSemanticsUnSupported informs the reflector that this client // doesn't support WatchList semantics. // // This is a synthetic method whose sole purpose is to satisfy the optional @@ -97,6 +93,10 @@ func (c *Clientset) IsWatchListSemanticsUnSupported() bool { // It's backed by a very simple object tracker that processes creates, updates and deletions as-is, // without applying any validations and/or defaults. It shouldn't be considered a replacement // for a real clientset and is mostly useful in simple unit tests. +// +// Compared to NewSimpleClientset, the Clientset returned here supports field tracking and thus +// server-side apply. Beware though that support in that for CRDs is missing +// (https://github.com/kubernetes/kubernetes/issues/126850). func NewClientset(objects ...runtime.Object) *Clientset { o := testing.NewFieldManagedObjectTracker( scheme, diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go index 54054dbfa2..e0dd80cf67 100644 --- a/pkg/client/informers/externalversions/factory.go +++ b/pkg/client/informers/externalversions/factory.go @@ -17,6 +17,7 @@ package externalversions import ( + context "context" reflect "reflect" sync "sync" time "time" @@ -27,6 +28,7 @@ import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" + wait "k8s.io/apimachinery/pkg/util/wait" cache "k8s.io/client-go/tools/cache" ) @@ -41,6 +43,7 @@ type sharedInformerFactory struct { defaultResync time.Duration customResync map[reflect.Type]time.Duration transform cache.TransformFunc + informerName *cache.InformerName informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -87,6 +90,21 @@ func WithTransform(transform cache.TransformFunc) SharedInformerOption { } } +// WithInformerName sets the InformerName for informer identity used in metrics. +// The InformerName must be created via cache.NewInformerName() at startup, +// which validates global uniqueness. Each informer type will register its +// GVR under this name. +func WithInformerName(informerName *cache.InformerName) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.informerName = informerName + return factory + } +} + +func (f *sharedInformerFactory) InformerName() *cache.InformerName { + return f.informerName +} + // NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { return NewSharedInformerFactoryWithOptions(client, defaultResync) @@ -121,6 +139,10 @@ func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResy } func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.StartWithContext(wait.ContextForChannel(stopCh)) +} + +func (f *sharedInformerFactory) StartWithContext(ctx context.Context) { f.lock.Lock() defer f.lock.Unlock() @@ -130,15 +152,9 @@ func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { for informerType, informer := range f.informers { if !f.startedInformers[informerType] { - f.wg.Add(1) - // We need a new variable in each loop iteration, - // otherwise the goroutine would use the loop variable - // and that keeps changing. - informer := informer - go func() { - defer f.wg.Done() - informer.Run(stopCh) - }() + f.wg.Go(func() { + informer.RunWithContext(ctx) + }) f.startedInformers[informerType] = true } } @@ -151,9 +167,15 @@ func (f *sharedInformerFactory) Shutdown() { // Will return immediately if there is nothing to wait for. f.wg.Wait() + f.informerName.Release() } func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + result := f.WaitForCacheSyncWithContext(wait.ContextForChannel(stopCh)) + return result.Synced +} + +func (f *sharedInformerFactory) WaitForCacheSyncWithContext(ctx context.Context) cache.SyncResult { informers := func() map[reflect.Type]cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -167,10 +189,31 @@ func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[ref return informers }() - res := map[reflect.Type]bool{} + // Wait for informers to sync, without polling. + cacheSyncs := make([]cache.DoneChecker, 0, len(informers)) + for _, informer := range informers { + cacheSyncs = append(cacheSyncs, informer.HasSyncedChecker()) + } + cache.WaitFor(ctx, "" /* no logging */, cacheSyncs...) + + res := cache.SyncResult{ + Synced: make(map[reflect.Type]bool, len(informers)), + } + failed := false for informType, informer := range informers { - res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + hasSynced := informer.HasSynced() + if !hasSynced { + failed = true + } + res.Synced[informType] = hasSynced } + if failed { + // context.Cause is more informative than ctx.Err(). + // This must be non-nil, otherwise WaitFor wouldn't have stopped + // prematurely. + res.Err = context.Cause(ctx) + } + return res } @@ -192,7 +235,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer @@ -209,27 +254,46 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal // defer factory.WaitForStop() // Returns immediately if nothing was started. // genericInformer := factory.ForResource(resource) // typedInformer := factory.SomeAPIGroup().V1().SomeType() -// factory.Start(ctx.Done()) // Start processing these informers. -// synced := factory.WaitForCacheSync(ctx.Done()) -// for v, ok := range synced { -// if !ok { -// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) -// return -// } +// handle, err := typeInformer.Informer().AddEventHandler(...) +// if err != nil { +// return fmt.Errorf("register event handler: %v", err) +// } +// defer typeInformer.Informer().RemoveEventHandler(handle) // Avoids leaking goroutines. +// factory.StartWithContext(ctx) // Start processing these informers. +// synced := factory.WaitForCacheSyncWithContext(ctx) +// if err := synced.AsError(); err != nil { +// return err +// } +// for v := range synced { +// // Only if desired log some information similar to this. +// fmt.Fprintf(os.Stdout, "cache synced: %s", v) +// } +// +// // Also make sure that all of the initial cache events have been delivered. +// if !WaitFor(ctx, "event handler sync", handle.HasSyncedChecker()) { +// // Must have failed because of context. +// return fmt.Errorf("sync event handler: %w", context.Cause(ctx)) // } // // // Creating informers can also be created after Start, but then // // Start must be called again: // anotherGenericInformer := factory.ForResource(resource) -// factory.Start(ctx.Done()) +// factory.StartWithContext(ctx) type SharedInformerFactory interface { internalinterfaces.SharedInformerFactory // Start initializes all requested informers. They are handled in goroutines // which run until the stop channel gets closed. // Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync. + // + // Contextual logging: StartWithContext should be used instead of Start in code which supports contextual logging. Start(stopCh <-chan struct{}) + // StartWithContext initializes all requested informers. They are handled in goroutines + // which run until the context gets canceled. + // Warning: StartWithContext does not block. When run in a go-routine, it will race with a later WaitForCacheSync. + StartWithContext(ctx context.Context) + // Shutdown marks a factory as shutting down. At that point no new // informers can be started anymore and Start will return without // doing anything. @@ -244,8 +308,14 @@ type SharedInformerFactory interface { // WaitForCacheSync blocks until all started informers' caches were synced // or the stop channel gets closed. + // + // Contextual logging: WaitForCacheSync should be used instead of WaitForCacheSync in code which supports contextual logging. It also returns a more useful result. WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + // WaitForCacheSyncWithContext blocks until all started informers' caches were synced + // or the context gets canceled. + WaitForCacheSyncWithContext(ctx context.Context) cache.SyncResult + // ForResource gives generic access to a shared informer of the matching type. ForResource(resource schema.GroupVersionResource) (GenericInformer, error) diff --git a/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go index 54b77ad82f..f3112570d9 100644 --- a/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -32,7 +32,26 @@ type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexI type SharedInformerFactory interface { Start(stopCh <-chan struct{}) InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer + InformerName() *cache.InformerName } // TweakListOptionsFunc is a function that transforms a v1.ListOptions. type TweakListOptionsFunc func(*v1.ListOptions) + +// InformerOptions holds the options for creating an informer. +type InformerOptions struct { + // ResyncPeriod is the resync period for this informer. + // If not set, defaults to 0 (no resync). + ResyncPeriod time.Duration + + // Indexers are the indexers for this informer. + Indexers cache.Indexers + + // InformerName is used to uniquely identify this informer for metrics. + // If not set, metrics will not be published for this informer. + // Use cache.NewInformerName() to create an InformerName at startup. + InformerName *cache.InformerName + + // TweakListOptions is an optional function to modify the list options. + TweakListOptions TweakListOptionsFunc +} diff --git a/pkg/client/informers/externalversions/trainer/v1alpha1/clustertrainingruntime.go b/pkg/client/informers/externalversions/trainer/v1alpha1/clustertrainingruntime.go index 3ae3f7f96e..7acde9244f 100644 --- a/pkg/client/informers/externalversions/trainer/v1alpha1/clustertrainingruntime.go +++ b/pkg/client/informers/externalversions/trainer/v1alpha1/clustertrainingruntime.go @@ -26,6 +26,7 @@ import ( trainerv1alpha1 "github.com/kubeflow/trainer/v2/pkg/client/listers/trainer/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" watch "k8s.io/apimachinery/pkg/watch" cache "k8s.io/client-go/tools/cache" ) @@ -46,48 +47,61 @@ type clusterTrainingRuntimeInformer struct { // 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 NewClusterTrainingRuntimeInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredClusterTrainingRuntimeInformer(client, resyncPeriod, indexers, nil) + return NewClusterTrainingRuntimeInformerWithOptions(client, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers}) } // NewFilteredClusterTrainingRuntimeInformer constructs a new informer for ClusterTrainingRuntime 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 NewFilteredClusterTrainingRuntimeInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( + return NewClusterTrainingRuntimeInformerWithOptions(client, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions}) +} + +// NewClusterTrainingRuntimeInformerWithOptions constructs a new informer for ClusterTrainingRuntime type with additional options. +// 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 NewClusterTrainingRuntimeInformerWithOptions(client versioned.Interface, options internalinterfaces.InformerOptions) cache.SharedIndexInformer { + gvr := schema.GroupVersionResource{Group: "trainer.kubeflow.org", Version: "v1alpha1", Resource: "clustertrainingruntimes"} + identifier := options.InformerName.WithResource(gvr) + tweakListOptions := options.TweakListOptions + return cache.NewSharedIndexInformerWithOptions( cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + ListFunc: func(opts v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.TrainerV1alpha1().ClusterTrainingRuntimes().List(context.Background(), options) + return client.TrainerV1alpha1().ClusterTrainingRuntimes().List(context.Background(), opts) }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + WatchFunc: func(opts v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.TrainerV1alpha1().ClusterTrainingRuntimes().Watch(context.Background(), options) + return client.TrainerV1alpha1().ClusterTrainingRuntimes().Watch(context.Background(), opts) }, - ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + ListWithContextFunc: func(ctx context.Context, opts v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.TrainerV1alpha1().ClusterTrainingRuntimes().List(ctx, options) + return client.TrainerV1alpha1().ClusterTrainingRuntimes().List(ctx, opts) }, - WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + WatchFuncWithContext: func(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.TrainerV1alpha1().ClusterTrainingRuntimes().Watch(ctx, options) + return client.TrainerV1alpha1().ClusterTrainingRuntimes().Watch(ctx, opts) }, }, client), &apistrainerv1alpha1.ClusterTrainingRuntime{}, - resyncPeriod, - indexers, + cache.SharedIndexInformerOptions{ + ResyncPeriod: options.ResyncPeriod, + Indexers: options.Indexers, + Identifier: identifier, + }, ) } func (f *clusterTrainingRuntimeInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredClusterTrainingRuntimeInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) + return NewClusterTrainingRuntimeInformerWithOptions(client, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions}) } func (f *clusterTrainingRuntimeInformer) Informer() cache.SharedIndexInformer { diff --git a/pkg/client/informers/externalversions/trainer/v1alpha1/trainingruntime.go b/pkg/client/informers/externalversions/trainer/v1alpha1/trainingruntime.go index 1064093c4f..63f393cae7 100644 --- a/pkg/client/informers/externalversions/trainer/v1alpha1/trainingruntime.go +++ b/pkg/client/informers/externalversions/trainer/v1alpha1/trainingruntime.go @@ -26,6 +26,7 @@ import ( trainerv1alpha1 "github.com/kubeflow/trainer/v2/pkg/client/listers/trainer/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" watch "k8s.io/apimachinery/pkg/watch" cache "k8s.io/client-go/tools/cache" ) @@ -47,48 +48,61 @@ type trainingRuntimeInformer struct { // 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 NewTrainingRuntimeInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredTrainingRuntimeInformer(client, namespace, resyncPeriod, indexers, nil) + return NewTrainingRuntimeInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers}) } // NewFilteredTrainingRuntimeInformer constructs a new informer for TrainingRuntime 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 NewFilteredTrainingRuntimeInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( + return NewTrainingRuntimeInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions}) +} + +// NewTrainingRuntimeInformerWithOptions constructs a new informer for TrainingRuntime type with additional options. +// 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 NewTrainingRuntimeInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer { + gvr := schema.GroupVersionResource{Group: "trainer.kubeflow.org", Version: "v1alpha1", Resource: "trainingruntimes"} + identifier := options.InformerName.WithResource(gvr) + tweakListOptions := options.TweakListOptions + return cache.NewSharedIndexInformerWithOptions( cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + ListFunc: func(opts v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.TrainerV1alpha1().TrainingRuntimes(namespace).List(context.Background(), options) + return client.TrainerV1alpha1().TrainingRuntimes(namespace).List(context.Background(), opts) }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + WatchFunc: func(opts v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.TrainerV1alpha1().TrainingRuntimes(namespace).Watch(context.Background(), options) + return client.TrainerV1alpha1().TrainingRuntimes(namespace).Watch(context.Background(), opts) }, - ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + ListWithContextFunc: func(ctx context.Context, opts v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.TrainerV1alpha1().TrainingRuntimes(namespace).List(ctx, options) + return client.TrainerV1alpha1().TrainingRuntimes(namespace).List(ctx, opts) }, - WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + WatchFuncWithContext: func(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.TrainerV1alpha1().TrainingRuntimes(namespace).Watch(ctx, options) + return client.TrainerV1alpha1().TrainingRuntimes(namespace).Watch(ctx, opts) }, }, client), &apistrainerv1alpha1.TrainingRuntime{}, - resyncPeriod, - indexers, + cache.SharedIndexInformerOptions{ + ResyncPeriod: options.ResyncPeriod, + Indexers: options.Indexers, + Identifier: identifier, + }, ) } func (f *trainingRuntimeInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredTrainingRuntimeInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) + return NewTrainingRuntimeInformerWithOptions(client, f.namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions}) } func (f *trainingRuntimeInformer) Informer() cache.SharedIndexInformer { diff --git a/pkg/client/informers/externalversions/trainer/v1alpha1/trainjob.go b/pkg/client/informers/externalversions/trainer/v1alpha1/trainjob.go index eec8e08336..f341b849cd 100644 --- a/pkg/client/informers/externalversions/trainer/v1alpha1/trainjob.go +++ b/pkg/client/informers/externalversions/trainer/v1alpha1/trainjob.go @@ -26,6 +26,7 @@ import ( trainerv1alpha1 "github.com/kubeflow/trainer/v2/pkg/client/listers/trainer/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" watch "k8s.io/apimachinery/pkg/watch" cache "k8s.io/client-go/tools/cache" ) @@ -47,48 +48,61 @@ type trainJobInformer struct { // 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 NewTrainJobInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredTrainJobInformer(client, namespace, resyncPeriod, indexers, nil) + return NewTrainJobInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers}) } // NewFilteredTrainJobInformer constructs a new informer for TrainJob 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 NewFilteredTrainJobInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( + return NewTrainJobInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions}) +} + +// NewTrainJobInformerWithOptions constructs a new informer for TrainJob type with additional options. +// 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 NewTrainJobInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer { + gvr := schema.GroupVersionResource{Group: "trainer.kubeflow.org", Version: "v1alpha1", Resource: "trainjobs"} + identifier := options.InformerName.WithResource(gvr) + tweakListOptions := options.TweakListOptions + return cache.NewSharedIndexInformerWithOptions( cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + ListFunc: func(opts v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.TrainerV1alpha1().TrainJobs(namespace).List(context.Background(), options) + return client.TrainerV1alpha1().TrainJobs(namespace).List(context.Background(), opts) }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + WatchFunc: func(opts v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.TrainerV1alpha1().TrainJobs(namespace).Watch(context.Background(), options) + return client.TrainerV1alpha1().TrainJobs(namespace).Watch(context.Background(), opts) }, - ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + ListWithContextFunc: func(ctx context.Context, opts v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.TrainerV1alpha1().TrainJobs(namespace).List(ctx, options) + return client.TrainerV1alpha1().TrainJobs(namespace).List(ctx, opts) }, - WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + WatchFuncWithContext: func(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.TrainerV1alpha1().TrainJobs(namespace).Watch(ctx, options) + return client.TrainerV1alpha1().TrainJobs(namespace).Watch(ctx, opts) }, }, client), &apistrainerv1alpha1.TrainJob{}, - resyncPeriod, - indexers, + cache.SharedIndexInformerOptions{ + ResyncPeriod: options.ResyncPeriod, + Indexers: options.Indexers, + Identifier: identifier, + }, ) } func (f *trainJobInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredTrainJobInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) + return NewTrainJobInformerWithOptions(client, f.namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions}) } func (f *trainJobInformer) Informer() cache.SharedIndexInformer { diff --git a/pkg/runtime/framework/plugins/jobset/jobset_test.go b/pkg/runtime/framework/plugins/jobset/jobset_test.go index e41502834e..134343c07b 100644 --- a/pkg/runtime/framework/plugins/jobset/jobset_test.go +++ b/pkg/runtime/framework/plugins/jobset/jobset_test.go @@ -1832,7 +1832,16 @@ func TestValidate(t *testing.T) { } warnings, errs := p.(framework.CustomValidationPlugin).Validate(ctx, tc.info, tc.oldObj, tc.newObj) - if diff := cmp.Diff(tc.wantError, errs); len(diff) != 0 { + errComparer := cmp.Comparer(func(a, b *field.Error) bool { + if a == nil && b == nil { + return true + } + if a == nil || b == nil { + return false + } + return a.Type == b.Type && a.Field == b.Field && a.Detail == b.Detail + }) + if diff := cmp.Diff(tc.wantError, errs, errComparer); len(diff) != 0 { t.Errorf("Unexpected error from Validate (-want, +got): %s", diff) } if diff := cmp.Diff(tc.wantWarnings, warnings); len(diff) != 0 {