summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/annotations/annotations.go76
-rw-r--r--pkg/api/handlers/compat/containers_stats.go2
-rw-r--r--pkg/api/handlers/compat/exec.go2
-rw-r--r--pkg/api/handlers/compat/images_prune.go2
-rw-r--r--pkg/api/handlers/compat/networks.go2
-rw-r--r--pkg/api/handlers/libpod/generate.go34
-rw-r--r--pkg/api/handlers/libpod/images.go25
-rw-r--r--pkg/api/handlers/libpod/play.go91
-rw-r--r--pkg/api/handlers/utils/images.go2
-rw-r--r--pkg/api/server/register_exec.go2
-rw-r--r--pkg/api/server/register_images.go4
-rw-r--r--pkg/api/server/register_networks.go11
-rw-r--r--pkg/api/server/swagger.go9
-rw-r--r--pkg/bindings/containers/attach.go25
-rw-r--r--pkg/bindings/containers/checkpoint.go9
-rw-r--r--pkg/bindings/containers/term_unix.go25
-rw-r--r--pkg/bindings/containers/term_windows.go69
-rw-r--r--pkg/bindings/containers/types.go23
-rw-r--r--pkg/bindings/containers/types_restore_options.go15
-rw-r--r--pkg/bindings/generator/generator.go1
-rw-r--r--pkg/bindings/images/build_unix.go1
-rw-r--r--pkg/bindings/images/types.go8
-rw-r--r--pkg/bindings/images/types_import_options.go45
-rw-r--r--pkg/bindings/images/types_remove_options.go15
-rw-r--r--pkg/bindings/play/play.go39
-rw-r--r--pkg/bindings/play/types.go2
-rw-r--r--pkg/bindings/play/types_kube_options.go15
-rw-r--r--pkg/bindings/test/attach_test.go3
-rw-r--r--pkg/bindings/test/auth_test.go3
-rw-r--r--pkg/bindings/test/common_test.go2
-rw-r--r--pkg/bindings/test/containers_test.go3
-rw-r--r--pkg/checkpoint/crutils/checkpoint_restore_utils.go9
-rw-r--r--pkg/criu/criu.go1
-rw-r--r--pkg/criu/criu_unsupported.go1
-rw-r--r--pkg/ctime/ctime_linux.go1
-rw-r--r--pkg/ctime/ctime_unsupported.go1
-rw-r--r--pkg/domain/entities/engine_container.go6
-rw-r--r--pkg/domain/entities/images.go3
-rw-r--r--pkg/domain/entities/play.go4
-rw-r--r--pkg/domain/entities/pods.go1
-rw-r--r--pkg/domain/entities/types.go4
-rw-r--r--pkg/domain/entities/volumes.go14
-rw-r--r--pkg/domain/filters/containers.go6
-rw-r--r--pkg/domain/filters/pods.go6
-rw-r--r--pkg/domain/infra/abi/containers.go7
-rw-r--r--pkg/domain/infra/abi/generate.go2
-rw-r--r--pkg/domain/infra/abi/images.go15
-rw-r--r--pkg/domain/infra/abi/play.go79
-rw-r--r--pkg/domain/infra/abi/play_test.go4
-rw-r--r--pkg/domain/infra/abi/terminal/sigproxy_linux.go2
-rw-r--r--pkg/domain/infra/abi/terminal/terminal_linux.go2
-rw-r--r--pkg/domain/infra/abi/volumes.go35
-rw-r--r--pkg/domain/infra/runtime_abi.go1
-rw-r--r--pkg/domain/infra/runtime_abi_unsupported.go1
-rw-r--r--pkg/domain/infra/runtime_libpod.go1
-rw-r--r--pkg/domain/infra/runtime_proxy.go1
-rw-r--r--pkg/domain/infra/runtime_tunnel.go1
-rw-r--r--pkg/domain/infra/tunnel/containers.go8
-rw-r--r--pkg/domain/infra/tunnel/events.go2
-rw-r--r--pkg/domain/infra/tunnel/images.go3
-rw-r--r--pkg/domain/infra/tunnel/play.go12
-rw-r--r--pkg/domain/infra/tunnel/volumes.go8
-rw-r--r--pkg/env/env.go2
-rw-r--r--pkg/env/env_unix.go1
-rw-r--r--pkg/errorhandling/errorhandling.go2
-rw-r--r--pkg/inspect/inspect.go6
-rw-r--r--pkg/k8s.io/README.md6
-rw-r--r--pkg/k8s.io/api/LICENSE202
-rw-r--r--pkg/k8s.io/api/apps/v1/types.go831
-rw-r--r--pkg/k8s.io/api/core/v1/annotation_key_constants.go151
-rw-r--r--pkg/k8s.io/api/core/v1/resource.go60
-rw-r--r--pkg/k8s.io/api/core/v1/types.go4468
-rw-r--r--pkg/k8s.io/apimachinery/LICENSE202
-rw-r--r--pkg/k8s.io/apimachinery/pkg/api/resource/amount.go299
-rw-r--r--pkg/k8s.io/apimachinery/pkg/api/resource/math.go304
-rw-r--r--pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go693
-rw-r--r--pkg/k8s.io/apimachinery/pkg/api/resource/scale_int.go95
-rw-r--r--pkg/k8s.io/apimachinery/pkg/api/resource/suffix.go198
-rw-r--r--pkg/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go55
-rw-r--r--pkg/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time.go171
-rw-r--r--pkg/k8s.io/apimachinery/pkg/apis/meta/v1/time.go172
-rw-r--r--pkg/k8s.io/apimachinery/pkg/apis/meta/v1/types.go1332
-rw-r--r--pkg/k8s.io/apimachinery/pkg/types/uid.go22
-rw-r--r--pkg/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go43
-rw-r--r--pkg/k8s.io/apimachinery/pkg/util/intstr/intstr.go113
-rw-r--r--pkg/kubeutils/resize.go3
-rw-r--r--pkg/lookup/lookup.go2
-rw-r--r--pkg/machine/config.go9
-rw-r--r--pkg/machine/fcos.go1
-rw-r--r--pkg/machine/fedora.go6
-rw-r--r--pkg/machine/ignition.go28
-rw-r--r--pkg/machine/ignition_darwin.go3
-rw-r--r--pkg/machine/ignition_schema.go1
-rw-r--r--pkg/machine/ignition_windows.go3
-rw-r--r--pkg/machine/keys.go1
-rw-r--r--pkg/machine/machine_unsupported.go1
-rw-r--r--pkg/machine/pull.go5
-rw-r--r--pkg/machine/qemu/config.go9
-rw-r--r--pkg/machine/qemu/machine.go193
-rw-r--r--pkg/machine/qemu/machine_unsupported.go1
-rw-r--r--pkg/machine/qemu/options_darwin_arm64.go1
-rw-r--r--pkg/machine/wsl/machine_unsupported.go1
-rw-r--r--pkg/rootless/rootless.go14
-rw-r--r--pkg/rootless/rootless_linux.go1
-rw-r--r--pkg/rootless/rootless_unsupported.go1
-rw-r--r--pkg/rootlessport/rootlessport_linux.go1
-rw-r--r--pkg/servicereaper/service.go3
-rw-r--r--pkg/signal/signal_common.go2
-rw-r--r--pkg/signal/signal_linux.go4
-rw-r--r--pkg/signal/signal_linux_mipsx.go1
-rw-r--r--pkg/signal/signal_unix.go100
-rw-r--r--pkg/signal/signal_unsupported.go3
-rw-r--r--pkg/specgen/config_unsupported.go1
-rw-r--r--pkg/specgen/generate/config_linux.go4
-rw-r--r--pkg/specgen/generate/config_linux_cgo.go1
-rw-r--r--pkg/specgen/generate/config_linux_nocgo.go1
-rw-r--r--pkg/specgen/generate/container_create.go4
-rw-r--r--pkg/specgen/generate/kube/kube.go10
-rw-r--r--pkg/specgen/generate/kube/kube_test.go2
-rw-r--r--pkg/specgen/generate/kube/play_test.go6
-rw-r--r--pkg/specgen/generate/kube/seccomp.go2
-rw-r--r--pkg/specgen/generate/kube/volume.go2
-rw-r--r--pkg/specgen/generate/oci.go6
-rw-r--r--pkg/specgen/generate/pod_create.go1
-rw-r--r--pkg/specgen/generate/ports_bench_test.go2
-rw-r--r--pkg/specgen/specgen.go4
-rw-r--r--pkg/specgenutil/specgen.go6
-rw-r--r--pkg/systemd/dbus.go1
-rw-r--r--pkg/systemd/generate/common.go14
-rw-r--r--pkg/systemd/generate/containers.go8
-rw-r--r--pkg/systemd/generate/containers_test.go42
-rw-r--r--pkg/systemd/generate/pods.go7
-rw-r--r--pkg/systemd/generate/pods_test.go44
-rw-r--r--pkg/terminal/console_unix.go3
-rw-r--r--pkg/terminal/console_windows.go1
-rw-r--r--pkg/util/camelcase/camelcase.go4
-rw-r--r--pkg/util/mountOpts_other.go1
-rw-r--r--pkg/util/utils.go4
-rw-r--r--pkg/util/utils_darwin.go3
-rw-r--r--pkg/util/utils_supported.go51
-rw-r--r--pkg/util/utils_unsupported.go1
-rw-r--r--pkg/util/utils_windows.go1
142 files changed, 10513 insertions, 356 deletions
diff --git a/pkg/annotations/annotations.go b/pkg/annotations/annotations.go
index 8badab20d..a22222f10 100644
--- a/pkg/annotations/annotations.go
+++ b/pkg/annotations/annotations.go
@@ -1,122 +1,122 @@
package annotations
const (
- // Annotations carries the received Kubelet annotations
+ // Annotations carries the received Kubelet annotations.
Annotations = "io.kubernetes.cri-o.Annotations"
- // ContainerID is the container ID annotation
+ // ContainerID is the container ID annotation.
ContainerID = "io.kubernetes.cri-o.ContainerID"
- // ContainerName is the container name annotation
+ // ContainerName is the container name annotation.
ContainerName = "io.kubernetes.cri-o.ContainerName"
- // ContainerType is the container type (sandbox or container) annotation
+ // ContainerType is the container type (sandbox or container) annotation.
ContainerType = "io.kubernetes.cri-o.ContainerType"
- // Created is the container creation time annotation
+ // Created is the container creation time annotation.
Created = "io.kubernetes.cri-o.Created"
- // HostName is the container host name annotation
+ // HostName is the container host name annotation.
HostName = "io.kubernetes.cri-o.HostName"
- // CgroupParent is the sandbox cgroup parent
+ // CgroupParent is the sandbox cgroup parent.
CgroupParent = "io.kubernetes.cri-o.CgroupParent"
- // IP is the container ipv4 or ipv6 address
+ // IP is the container ipv4 or ipv6 address.
IP = "io.kubernetes.cri-o.IP"
- // NamespaceOptions store the options for namespaces
+ // NamespaceOptions store the options for namespaces.
NamespaceOptions = "io.kubernetes.cri-o.NamespaceOptions"
- // SeccompProfilePath is the node seccomp profile path
+ // SeccompProfilePath is the node seccomp profile path.
SeccompProfilePath = "io.kubernetes.cri-o.SeccompProfilePath"
- // Image is the container image ID annotation
+ // Image is the container image ID annotation.
Image = "io.kubernetes.cri-o.Image"
- // ImageName is the container image name annotation
+ // ImageName is the container image name annotation.
ImageName = "io.kubernetes.cri-o.ImageName"
- // ImageRef is the container image ref annotation
+ // ImageRef is the container image ref annotation.
ImageRef = "io.kubernetes.cri-o.ImageRef"
- // KubeName is the kubernetes name annotation
+ // KubeName is the kubernetes name annotation.
KubeName = "io.kubernetes.cri-o.KubeName"
- // PortMappings holds the port mappings for the sandbox
+ // PortMappings holds the port mappings for the sandbox.
PortMappings = "io.kubernetes.cri-o.PortMappings"
- // Labels are the kubernetes labels annotation
+ // Labels are the kubernetes labels annotation.
Labels = "io.kubernetes.cri-o.Labels"
- // LogPath is the container logging path annotation
+ // LogPath is the container logging path annotation.
LogPath = "io.kubernetes.cri-o.LogPath"
- // Metadata is the container metadata annotation
+ // Metadata is the container metadata annotation.
Metadata = "io.kubernetes.cri-o.Metadata"
- // Name is the pod name annotation
+ // Name is the pod name annotation.
Name = "io.kubernetes.cri-o.Name"
- // Namespace is the pod namespace annotation
+ // Namespace is the pod namespace annotation.
Namespace = "io.kubernetes.cri-o.Namespace"
- // PrivilegedRuntime is the annotation for the privileged runtime path
+ // PrivilegedRuntime is the annotation for the privileged runtime path.
PrivilegedRuntime = "io.kubernetes.cri-o.PrivilegedRuntime"
- // ResolvPath is the resolver configuration path annotation
+ // ResolvPath is the resolver configuration path annotation.
ResolvPath = "io.kubernetes.cri-o.ResolvPath"
- // HostnamePath is the path to /etc/hostname to bind mount annotation
+ // HostnamePath is the path to /etc/hostname to bind mount annotation.
HostnamePath = "io.kubernetes.cri-o.HostnamePath"
- // SandboxID is the sandbox ID annotation
+ // SandboxID is the sandbox ID annotation.
SandboxID = "io.kubernetes.cri-o.SandboxID"
- // SandboxName is the sandbox name annotation
+ // SandboxName is the sandbox name annotation.
SandboxName = "io.kubernetes.cri-o.SandboxName"
- // ShmPath is the shared memory path annotation
+ // ShmPath is the shared memory path annotation.
ShmPath = "io.kubernetes.cri-o.ShmPath"
- // MountPoint is the mount point of the container rootfs
+ // MountPoint is the mount point of the container rootfs.
MountPoint = "io.kubernetes.cri-o.MountPoint"
- // RuntimeHandler is the annotation for runtime handler
+ // RuntimeHandler is the annotation for runtime handler.
RuntimeHandler = "io.kubernetes.cri-o.RuntimeHandler"
- // TTY is the terminal path annotation
+ // TTY is the terminal path annotation.
TTY = "io.kubernetes.cri-o.TTY"
- // Stdin is the stdin annotation
+ // Stdin is the stdin annotation.
Stdin = "io.kubernetes.cri-o.Stdin"
- // StdinOnce is the stdin_once annotation
+ // StdinOnce is the stdin_once annotation.
StdinOnce = "io.kubernetes.cri-o.StdinOnce"
- // Volumes is the volumes annotation
+ // Volumes is the volumes annotation.
Volumes = "io.kubernetes.cri-o.Volumes"
- // HostNetwork indicates whether the host network namespace is used or not
+ // HostNetwork indicates whether the host network namespace is used or not.
HostNetwork = "io.kubernetes.cri-o.HostNetwork"
- // CNIResult is the JSON string representation of the Result from CNI
+ // CNIResult is the JSON string representation of the Result from CNI.
CNIResult = "io.kubernetes.cri-o.CNIResult"
// ContainerManager is the annotation key for indicating the creator and
- // manager of the container
+ // manager of the container.
ContainerManager = "io.container.manager"
)
// ContainerType values
const (
- // ContainerTypeSandbox represents a pod sandbox container
+ // ContainerTypeSandbox represents a pod sandbox container.
ContainerTypeSandbox = "sandbox"
- // ContainerTypeContainer represents a container running within a pod
+ // ContainerTypeContainer represents a container running within a pod.
ContainerTypeContainer = "container"
)
// ContainerManagerLibpod indicates that libpod created and manages the
-// container
+// container.
const ContainerManagerLibpod = "libpod"
diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go
index 99f14d02f..77b16b03e 100644
--- a/pkg/api/handlers/compat/containers_stats.go
+++ b/pkg/api/handlers/compat/containers_stats.go
@@ -56,7 +56,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
return
}
- stats, err := ctnr.GetContainerStats(&define.ContainerStats{})
+ stats, err := ctnr.GetContainerStats(nil)
if err != nil {
utils.InternalServerError(w, errors.Wrapf(err, "failed to obtain Container %s stats", name))
return
diff --git a/pkg/api/handlers/compat/exec.go b/pkg/api/handlers/compat/exec.go
index c6f7e0318..def16d1b5 100644
--- a/pkg/api/handlers/compat/exec.go
+++ b/pkg/api/handlers/compat/exec.go
@@ -73,7 +73,7 @@ func ExecCreateHandler(w http.ResponseWriter, r *http.Request) {
// Run the exit command after 5 minutes, to mimic Docker's exec cleanup
// behavior.
- libpodConfig.ExitCommandDelay = 5 * 60
+ libpodConfig.ExitCommandDelay = runtimeConfig.Engine.ExitCommandDelay
sessID, err := ctr.ExecCreate(libpodConfig)
if err != nil {
diff --git a/pkg/api/handlers/compat/images_prune.go b/pkg/api/handlers/compat/images_prune.go
index 88776dc49..c0be9da7d 100644
--- a/pkg/api/handlers/compat/images_prune.go
+++ b/pkg/api/handlers/compat/images_prune.go
@@ -43,7 +43,7 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
return
}
- idr := make([]types.ImageDeleteResponseItem, len(imagePruneReports))
+ idr := make([]types.ImageDeleteResponseItem, 0, len(imagePruneReports))
var reclaimedSpace uint64
var errorMsg bytes.Buffer
for _, p := range imagePruneReports {
diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go
index eb1a5d59c..89d914e0a 100644
--- a/pkg/api/handlers/compat/networks.go
+++ b/pkg/api/handlers/compat/networks.go
@@ -242,7 +242,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
body := struct {
ID string `json:"Id"`
- Warning []string
+ Warning string
}{
ID: newNetwork.ID,
}
diff --git a/pkg/api/handlers/libpod/generate.go b/pkg/api/handlers/libpod/generate.go
index 7e08dd4a8..28785b00d 100644
--- a/pkg/api/handlers/libpod/generate.go
+++ b/pkg/api/handlers/libpod/generate.go
@@ -25,18 +25,15 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
RestartSec uint `schema:"restartSec"`
StopTimeout uint `schema:"stopTimeout"`
StartTimeout uint `schema:"startTimeout"`
- ContainerPrefix string `schema:"containerPrefix"`
- PodPrefix string `schema:"podPrefix"`
- Separator string `schema:"separator"`
+ ContainerPrefix *string `schema:"containerPrefix"`
+ PodPrefix *string `schema:"podPrefix"`
+ Separator *string `schema:"separator"`
Wants []string `schema:"wants"`
After []string `schema:"after"`
Requires []string `schema:"requires"`
}{
- StartTimeout: 0,
- StopTimeout: util.DefaultContainerConfig().Engine.StopTimeout,
- ContainerPrefix: "container",
- PodPrefix: "pod",
- Separator: "-",
+ StartTimeout: 0,
+ StopTimeout: util.DefaultContainerConfig().Engine.StopTimeout,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
@@ -44,6 +41,21 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
return
}
+ var ContainerPrefix = "container"
+ if query.ContainerPrefix != nil {
+ ContainerPrefix = *query.ContainerPrefix
+ }
+
+ var PodPrefix = "pod"
+ if query.PodPrefix != nil {
+ PodPrefix = *query.PodPrefix
+ }
+
+ var Separator = "-"
+ if query.Separator != nil {
+ Separator = *query.Separator
+ }
+
containerEngine := abi.ContainerEngine{Libpod: runtime}
options := entities.GenerateSystemdOptions{
Name: query.Name,
@@ -53,9 +65,9 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
RestartPolicy: query.RestartPolicy,
StartTimeout: &query.StartTimeout,
StopTimeout: &query.StopTimeout,
- ContainerPrefix: query.ContainerPrefix,
- PodPrefix: query.PodPrefix,
- Separator: query.Separator,
+ ContainerPrefix: ContainerPrefix,
+ PodPrefix: PodPrefix,
+ Separator: Separator,
RestartSec: &query.RestartSec,
Wants: query.Wants,
After: query.After,
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index eb9fb12a6..cddf4c205 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -367,10 +367,13 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
- Changes []string `schema:"changes"`
- Message string `schema:"message"`
- Reference string `schema:"reference"`
- URL string `schema:"URL"`
+ Changes []string `schema:"changes"`
+ Message string `schema:"message"`
+ Reference string `schema:"reference"`
+ URL string `schema:"URL"`
+ OS string `schema:"OS"`
+ Architecture string `schema:"Architecture"`
+ Variant string `schema:"Variant"`
}{
// Add defaults here once needed.
}
@@ -402,10 +405,13 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
imageEngine := abi.ImageEngine{Libpod: runtime}
importOptions := entities.ImageImportOptions{
- Changes: query.Changes,
- Message: query.Message,
- Reference: query.Reference,
- Source: source,
+ Changes: query.Changes,
+ Message: query.Message,
+ Reference: query.Reference,
+ OS: query.OS,
+ Architecture: query.Architecture,
+ Variant: query.Variant,
+ Source: source,
}
report, err := imageEngine.Import(r.Context(), importOptions)
if err != nil {
@@ -613,6 +619,7 @@ func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) {
query := struct {
All bool `schema:"all"`
Force bool `schema:"force"`
+ Ignore bool `schema:"ignore"`
Images []string `schema:"images"`
}{}
@@ -621,7 +628,7 @@ func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) {
return
}
- opts := entities.ImageRemoveOptions{All: query.All, Force: query.Force}
+ opts := entities.ImageRemoveOptions{All: query.All, Force: query.Force, Ignore: query.Ignore}
imageEngine := abi.ImageEngine{Libpod: runtime}
rmReport, rmErrors := imageEngine.Remove(r.Context(), query.Images, opts)
strErrs := errorhandling.ErrorsToStrings(rmErrors)
diff --git a/pkg/api/handlers/libpod/play.go b/pkg/api/handlers/libpod/play.go
index 515d0e5cf..ca9ada761 100644
--- a/pkg/api/handlers/libpod/play.go
+++ b/pkg/api/handlers/libpod/play.go
@@ -1,11 +1,8 @@
package libpod
import (
- "io"
- "io/ioutil"
"net"
"net/http"
- "os"
"github.com/containers/image/v5/types"
"github.com/containers/podman/v4/libpod"
@@ -16,21 +13,21 @@ import (
"github.com/containers/podman/v4/pkg/domain/infra/abi"
"github.com/gorilla/schema"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
)
func PlayKube(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
- Network []string `schema:"network"`
- TLSVerify bool `schema:"tlsVerify"`
- LogDriver string `schema:"logDriver"`
- LogOptions []string `schema:"logOptions"`
- Start bool `schema:"start"`
- StaticIPs []string `schema:"staticIPs"`
- StaticMACs []string `schema:"staticMACs"`
- NoHosts bool `schema:"noHosts"`
+ Annotations map[string]string `schema:"annotations"`
+ Network []string `schema:"network"`
+ TLSVerify bool `schema:"tlsVerify"`
+ LogDriver string `schema:"logDriver"`
+ LogOptions []string `schema:"logOptions"`
+ Start bool `schema:"start"`
+ StaticIPs []string `schema:"staticIPs"`
+ StaticMACs []string `schema:"staticMACs"`
+ NoHosts bool `schema:"noHosts"`
}{
TLSVerify: true,
Start: true,
@@ -61,28 +58,6 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
staticMACs = append(staticMACs, mac)
}
- // Fetch the K8s YAML file from the body, and copy it to a temp file.
- tmpfile, err := ioutil.TempFile("", "libpod-play-kube.yml")
- if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
- return
- }
- defer func() {
- if err := os.Remove(tmpfile.Name()); err != nil {
- logrus.Warn(err)
- }
- }()
- if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF {
- if err := tmpfile.Close(); err != nil {
- logrus.Warn(err)
- }
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
- return
- }
- if err := tmpfile.Close(); err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error closing temporary file"))
- return
- }
authConf, authfile, err := auth.GetCredentials(r)
if err != nil {
utils.Error(w, http.StatusBadRequest, err)
@@ -97,16 +72,17 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
containerEngine := abi.ContainerEngine{Libpod: runtime}
options := entities.PlayKubeOptions{
- Authfile: authfile,
- Username: username,
- Password: password,
- Networks: query.Network,
- NoHosts: query.NoHosts,
- Quiet: true,
- LogDriver: query.LogDriver,
- LogOptions: query.LogOptions,
- StaticIPs: staticIPs,
- StaticMACs: staticMACs,
+ Annotations: query.Annotations,
+ Authfile: authfile,
+ Username: username,
+ Password: password,
+ Networks: query.Network,
+ NoHosts: query.NoHosts,
+ Quiet: true,
+ LogDriver: query.LogDriver,
+ LogOptions: query.LogOptions,
+ StaticIPs: staticIPs,
+ StaticMACs: staticMACs,
}
if _, found := r.URL.Query()["tlsVerify"]; found {
options.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)
@@ -114,7 +90,8 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
if _, found := r.URL.Query()["start"]; found {
options.Start = types.NewOptionalBool(query.Start)
}
- report, err := containerEngine.PlayKube(r.Context(), tmpfile.Name(), options)
+ report, err := containerEngine.PlayKube(r.Context(), r.Body, options)
+ _ = r.Body.Close()
if err != nil {
utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error playing YAML file"))
return
@@ -124,30 +101,10 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
func PlayKubeDown(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
- tmpfile, err := ioutil.TempFile("", "libpod-play-kube.yml")
- if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
- return
- }
- defer func() {
- if err := os.Remove(tmpfile.Name()); err != nil {
- logrus.Warn(err)
- }
- }()
- if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF {
- if err := tmpfile.Close(); err != nil {
- logrus.Warn(err)
- }
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
- return
- }
- if err := tmpfile.Close(); err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error closing temporary file"))
- return
- }
containerEngine := abi.ContainerEngine{Libpod: runtime}
options := new(entities.PlayKubeDownOptions)
- report, err := containerEngine.PlayKubeDown(r.Context(), tmpfile.Name(), *options)
+ report, err := containerEngine.PlayKubeDown(r.Context(), r.Body, *options)
+ _ = r.Body.Close()
if err != nil {
utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error tearing down YAML file"))
return
diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go
index 15b16bc43..7154f5616 100644
--- a/pkg/api/handlers/utils/images.go
+++ b/pkg/api/handlers/utils/images.go
@@ -63,7 +63,7 @@ func IsRegistryReference(name string) error {
imageRef, err := alltransports.ParseImageName(name)
if err != nil {
// No supported transport -> assume a docker-stype reference.
- return nil
+ return nil // nolint: nilerr
}
if imageRef.Transport().Name() == docker.Transport.Name() {
return nil
diff --git a/pkg/api/server/register_exec.go b/pkg/api/server/register_exec.go
index c19ca7859..90136463d 100644
--- a/pkg/api/server/register_exec.go
+++ b/pkg/api/server/register_exec.go
@@ -169,7 +169,7 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// - application/json
// responses:
// 200:
- // description: no error
+ // $ref: "#/responses/InspectExecSession"
// 404:
// $ref: "#/responses/NoSuchExecInstance"
// 500:
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index 017310f12..89f808e7d 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -944,6 +944,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// name: force
// description: Force image removal (including containers using the images).
// type: boolean
+ // - in: query
+ // name: ignore
+ // description: Ignore if a specified image does not exist and do not throw an error.
+ // type: boolean
// produces:
// - application/json
// responses:
diff --git a/pkg/api/server/register_networks.go b/pkg/api/server/register_networks.go
index 4466c938f..b900aa953 100644
--- a/pkg/api/server/register_networks.go
+++ b/pkg/api/server/register_networks.go
@@ -105,8 +105,15 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
// schema:
// $ref: "#/definitions/NetworkCreateRequest"
// responses:
- // 200:
- // $ref: "#/responses/CompatNetworkCreate"
+ // 201:
+ // description: network created
+ // schema:
+ // type: object
+ // properties:
+ // Id:
+ // type: string
+ // Warning:
+ // type: string
// 400:
// $ref: "#/responses/BadParamError"
// 500:
diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go
index 9b652be87..6cf89581a 100644
--- a/pkg/api/server/swagger.go
+++ b/pkg/api/server/swagger.go
@@ -235,3 +235,12 @@ type swagSystemAuthResponse struct {
entities.AuthReport
}
}
+
+// Inspect response
+// swagger:response InspectExecSession
+type swagInspectExecSession struct {
+ // in:body
+ Body struct {
+ define.InspectExecSession
+ }
+}
diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go
index c6d434c87..0c6ebdd2f 100644
--- a/pkg/bindings/containers/attach.go
+++ b/pkg/bindings/containers/attach.go
@@ -10,14 +10,12 @@ import (
"net/http"
"net/url"
"os"
- "os/signal"
"reflect"
"strconv"
"time"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/bindings"
- sig "github.com/containers/podman/v4/pkg/signal"
"github.com/containers/podman/v4/utils"
"github.com/moby/term"
"github.com/pkg/errors"
@@ -94,7 +92,8 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri
// Unless all requirements are met, don't use "stdin" is a terminal
file, ok := stdin.(*os.File)
- needTTY := ok && terminal.IsTerminal(int(file.Fd())) && ctnr.Config.Tty
+ outFile, outOk := stdout.(*os.File)
+ needTTY := ok && outOk && terminal.IsTerminal(int(file.Fd())) && ctnr.Config.Tty
if needTTY {
state, err := setRawTerminal(file)
if err != nil {
@@ -142,11 +141,10 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri
if needTTY {
winChange := make(chan os.Signal, 1)
- signal.Notify(winChange, sig.SIGWINCH)
winCtx, winCancel := context.WithCancel(ctx)
defer winCancel()
-
- attachHandleResize(ctx, winCtx, winChange, false, nameOrID, file)
+ notifyWinChange(winCtx, winChange, file, outFile)
+ attachHandleResize(ctx, winCtx, winChange, false, nameOrID, file, outFile)
}
// If we are attaching around a start, we need to "signal"
@@ -281,7 +279,7 @@ func DemuxFrame(r io.Reader, buffer []byte, length int) (frame []byte, err error
n, err := io.ReadFull(r, buffer[0:length])
if err != nil {
- return nil, nil
+ return nil, err
}
if n < length {
err = io.ErrUnexpectedEOF
@@ -345,9 +343,9 @@ func (f *rawFormatter) Format(entry *logrus.Entry) ([]byte, error) {
// This is intended to not be run as a goroutine, handling resizing for a container
// or exec session. It will call resize once and then starts a goroutine which calls resize on winChange
-func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, isExec bool, id string, file *os.File) {
+func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, isExec bool, id string, file *os.File, outFile *os.File) {
resize := func() {
- w, h, err := terminal.GetSize(int(file.Fd()))
+ w, h, err := getTermSize(file, outFile)
if err != nil {
logrus.Warnf("Failed to obtain TTY size: %v", err)
}
@@ -379,7 +377,7 @@ func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, i
// Configure the given terminal for raw mode
func setRawTerminal(file *os.File) (*terminal.State, error) {
- state, err := terminal.MakeRaw(int(file.Fd()))
+ state, err := makeRawTerm(file)
if err != nil {
return nil, err
}
@@ -402,6 +400,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
// TODO: Make this configurable (can't use streams' InputStream as it's
// buffered)
terminalFile := os.Stdin
+ terminalOutFile := os.Stdout
logrus.Debugf("Starting & Attaching to exec session ID %q", sessionID)
@@ -447,7 +446,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
}
logrus.SetFormatter(&logrus.TextFormatter{})
}()
- w, h, err := terminal.GetSize(int(terminalFile.Fd()))
+ w, h, err := getTermSize(terminalFile, terminalOutFile)
if err != nil {
logrus.Warnf("Failed to obtain TTY size: %v", err)
}
@@ -490,11 +489,11 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
if needTTY {
winChange := make(chan os.Signal, 1)
- signal.Notify(winChange, sig.SIGWINCH)
winCtx, winCancel := context.WithCancel(ctx)
defer winCancel()
- attachHandleResize(ctx, winCtx, winChange, true, sessionID, terminalFile)
+ notifyWinChange(winCtx, winChange, terminalFile, terminalOutFile)
+ attachHandleResize(ctx, winCtx, winChange, true, sessionID, terminalFile, terminalOutFile)
}
if options.GetAttachInput() {
diff --git a/pkg/bindings/containers/checkpoint.go b/pkg/bindings/containers/checkpoint.go
index 1d8c34b33..bcb944488 100644
--- a/pkg/bindings/containers/checkpoint.go
+++ b/pkg/bindings/containers/checkpoint.go
@@ -79,7 +79,14 @@ func Restore(ctx context.Context, nameOrID string, options *RestoreOptions) (*en
// Open the to-be-imported archive if needed.
var r io.Reader
- if i := options.GetImportAchive(); i != "" {
+ i := options.GetImportArchive()
+ if i == "" {
+ // backwards compat, ImportAchive is a typo but we still have to
+ // support this to avoid breaking users
+ // TODO: remove ImportAchive with 5.0
+ i = options.GetImportAchive()
+ }
+ if i != "" {
params.Set("import", "true")
r, err = os.Open(i)
if err != nil {
diff --git a/pkg/bindings/containers/term_unix.go b/pkg/bindings/containers/term_unix.go
new file mode 100644
index 000000000..2c976393f
--- /dev/null
+++ b/pkg/bindings/containers/term_unix.go
@@ -0,0 +1,25 @@
+//go:build !windows
+// +build !windows
+
+package containers
+
+import (
+ "context"
+ "os"
+ "os/signal"
+
+ sig "github.com/containers/podman/v4/pkg/signal"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+func makeRawTerm(stdin *os.File) (*terminal.State, error) {
+ return terminal.MakeRaw(int(stdin.Fd()))
+}
+
+func notifyWinChange(ctx context.Context, winChange chan os.Signal, stdin *os.File, stdout *os.File) {
+ signal.Notify(winChange, sig.SIGWINCH)
+}
+
+func getTermSize(stdin *os.File, stdout *os.File) (width, height int, err error) {
+ return terminal.GetSize(int(stdin.Fd()))
+}
diff --git a/pkg/bindings/containers/term_windows.go b/pkg/bindings/containers/term_windows.go
new file mode 100644
index 000000000..11d4bd50d
--- /dev/null
+++ b/pkg/bindings/containers/term_windows.go
@@ -0,0 +1,69 @@
+package containers
+
+import (
+ "context"
+ "os"
+ "time"
+
+ sig "github.com/containers/podman/v4/pkg/signal"
+ "golang.org/x/crypto/ssh/terminal"
+ "golang.org/x/sys/windows"
+)
+
+func makeRawTerm(stdin *os.File) (*terminal.State, error) {
+ state, err := terminal.MakeRaw(int(stdin.Fd()))
+ if err != nil {
+ return nil, err
+ }
+
+ // Attempt VT if supported (recent versions of Windows 10+)
+ var raw uint32
+ handle := windows.Handle(stdin.Fd())
+ if err := windows.GetConsoleMode(handle, &raw); err != nil {
+ return nil, err
+ }
+
+ tryVT := raw | windows.ENABLE_VIRTUAL_TERMINAL_INPUT
+
+ if err := windows.SetConsoleMode(handle, tryVT); err != nil {
+ if err := windows.SetConsoleMode(handle, raw); err != nil {
+ return nil, err
+ }
+ }
+
+ return state, nil
+}
+
+func notifyWinChange(ctx context.Context, winChange chan os.Signal, stdin *os.File, stdout *os.File) {
+ // Simulate WINCH with polling
+ go func() {
+ var lastW int
+ var lastH int
+
+ d := time.Millisecond * 250
+ timer := time.NewTimer(d)
+ defer timer.Stop()
+ for ; ; timer.Reset(d) {
+ select {
+ case <-ctx.Done():
+ return
+ case <-timer.C:
+ break
+ }
+
+ w, h, err := terminal.GetSize(int(stdout.Fd()))
+ if err != nil {
+ continue
+ }
+ if w != lastW || h != lastH {
+ winChange <- sig.SIGWINCH
+ lastW, lastH = w, h
+ }
+ }
+ }()
+
+}
+
+func getTermSize(stdin *os.File, stdout *os.File) (width, height int, err error) {
+ return terminal.GetSize(int(stdout.Fd()))
+}
diff --git a/pkg/bindings/containers/types.go b/pkg/bindings/containers/types.go
index 66b90af9b..c87f82bf4 100644
--- a/pkg/bindings/containers/types.go
+++ b/pkg/bindings/containers/types.go
@@ -64,14 +64,21 @@ type RestoreOptions struct {
IgnoreVolumes *bool
IgnoreStaticIP *bool
IgnoreStaticMAC *bool
- ImportAchive *string
- Keep *bool
- Name *string
- TCPEstablished *bool
- Pod *string
- PrintStats *bool
- PublishPorts []string
- FileLocks *bool
+ // ImportAchive is the path to an archive which contains the checkpoint data.
+ //
+ // Deprecated: Use ImportArchive instead. This field name is a typo and
+ // will be removed in a future major release.
+ ImportAchive *string
+ // ImportArchive is the path to an archive which contains the checkpoint data.
+ // ImportArchive is preferred over ImportAchive when both are set.
+ ImportArchive *string
+ Keep *bool
+ Name *string
+ TCPEstablished *bool
+ Pod *string
+ PrintStats *bool
+ PublishPorts []string
+ FileLocks *bool
}
//go:generate go run ../generator/generator.go CreateOptions
diff --git a/pkg/bindings/containers/types_restore_options.go b/pkg/bindings/containers/types_restore_options.go
index d2778396a..b1b14a704 100644
--- a/pkg/bindings/containers/types_restore_options.go
+++ b/pkg/bindings/containers/types_restore_options.go
@@ -92,6 +92,21 @@ func (o *RestoreOptions) GetImportAchive() string {
return *o.ImportAchive
}
+// WithImportArchive set field ImportArchive to given value
+func (o *RestoreOptions) WithImportArchive(value string) *RestoreOptions {
+ o.ImportArchive = &value
+ return o
+}
+
+// GetImportArchive returns value of field ImportArchive
+func (o *RestoreOptions) GetImportArchive() string {
+ if o.ImportArchive == nil {
+ var z string
+ return z
+ }
+ return *o.ImportArchive
+}
+
// WithKeep set field Keep to given value
func (o *RestoreOptions) WithKeep(value bool) *RestoreOptions {
o.Keep = &value
diff --git a/pkg/bindings/generator/generator.go b/pkg/bindings/generator/generator.go
index a224013ea..e69973be1 100644
--- a/pkg/bindings/generator/generator.go
+++ b/pkg/bindings/generator/generator.go
@@ -1,3 +1,4 @@
+//go:build ignore
// +build ignore
package main
diff --git a/pkg/bindings/images/build_unix.go b/pkg/bindings/images/build_unix.go
index 0afb1deb6..67a5e2998 100644
--- a/pkg/bindings/images/build_unix.go
+++ b/pkg/bindings/images/build_unix.go
@@ -1,3 +1,4 @@
+//go:build !windows
// +build !windows
package images
diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go
index a44a3527f..75cb38a0a 100644
--- a/pkg/bindings/images/types.go
+++ b/pkg/bindings/images/types.go
@@ -11,6 +11,8 @@ type RemoveOptions struct {
All *bool
// Forces removes all containers based on the image
Force *bool
+ // Ignore if a specified image does not exist and do not throw an error.
+ Ignore *bool
}
//go:generate go run ../generator/generator.go DiffOptions
@@ -101,6 +103,12 @@ type ImportOptions struct {
Reference *string
// Url to option image to import. Cannot be used with the reader
URL *string
+ // OS for the imported image
+ OS *string
+ // Architecture for the imported image
+ Architecture *string
+ // Variant for the imported image
+ Variant *string
}
//go:generate go run ../generator/generator.go PushOptions
diff --git a/pkg/bindings/images/types_import_options.go b/pkg/bindings/images/types_import_options.go
index ea66fa312..f958fe8b4 100644
--- a/pkg/bindings/images/types_import_options.go
+++ b/pkg/bindings/images/types_import_options.go
@@ -76,3 +76,48 @@ func (o *ImportOptions) GetURL() string {
}
return *o.URL
}
+
+// WithOS set field OS to given value
+func (o *ImportOptions) WithOS(value string) *ImportOptions {
+ o.OS = &value
+ return o
+}
+
+// GetOS returns value of field OS
+func (o *ImportOptions) GetOS() string {
+ if o.OS == nil {
+ var z string
+ return z
+ }
+ return *o.OS
+}
+
+// WithArchitecture set field Architecture to given value
+func (o *ImportOptions) WithArchitecture(value string) *ImportOptions {
+ o.Architecture = &value
+ return o
+}
+
+// GetArchitecture returns value of field Architecture
+func (o *ImportOptions) GetArchitecture() string {
+ if o.Architecture == nil {
+ var z string
+ return z
+ }
+ return *o.Architecture
+}
+
+// WithVariant set field Variant to given value
+func (o *ImportOptions) WithVariant(value string) *ImportOptions {
+ o.Variant = &value
+ return o
+}
+
+// GetVariant returns value of field Variant
+func (o *ImportOptions) GetVariant() string {
+ if o.Variant == nil {
+ var z string
+ return z
+ }
+ return *o.Variant
+}
diff --git a/pkg/bindings/images/types_remove_options.go b/pkg/bindings/images/types_remove_options.go
index 1fbe5f4ea..613a33183 100644
--- a/pkg/bindings/images/types_remove_options.go
+++ b/pkg/bindings/images/types_remove_options.go
@@ -46,3 +46,18 @@ func (o *RemoveOptions) GetForce() bool {
}
return *o.Force
}
+
+// WithIgnore set field Ignore to given value
+func (o *RemoveOptions) WithIgnore(value bool) *RemoveOptions {
+ o.Ignore = &value
+ return o
+}
+
+// GetIgnore returns value of field Ignore
+func (o *RemoveOptions) GetIgnore() bool {
+ if o.Ignore == nil {
+ var z bool
+ return z
+ }
+ return *o.Ignore
+}
diff --git a/pkg/bindings/play/play.go b/pkg/bindings/play/play.go
index d4018b6b3..8058a8514 100644
--- a/pkg/bindings/play/play.go
+++ b/pkg/bindings/play/play.go
@@ -2,6 +2,7 @@ package play
import (
"context"
+ "io"
"net/http"
"os"
"strconv"
@@ -14,20 +15,25 @@ import (
)
func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.PlayKubeReport, error) {
+ f, err := os.Open(path)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ return KubeWithBody(ctx, f, options)
+}
+
+func KubeWithBody(ctx context.Context, body io.Reader, options *KubeOptions) (*entities.PlayKubeReport, error) {
var report entities.PlayKubeReport
if options == nil {
options = new(KubeOptions)
}
- conn, err := bindings.GetClient(ctx)
- if err != nil {
- return nil, err
- }
- f, err := os.Open(path)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- defer f.Close()
params, err := options.ToParams()
if err != nil {
@@ -46,7 +52,7 @@ func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.Pla
return nil, err
}
- response, err := conn.DoRequest(ctx, f, http.MethodPost, "/play/kube", params, header)
+ response, err := conn.DoRequest(ctx, body, http.MethodPost, "/play/kube", params, header)
if err != nil {
return nil, err
}
@@ -60,12 +66,6 @@ func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.Pla
}
func KubeDown(ctx context.Context, path string) (*entities.PlayKubeReport, error) {
- var report entities.PlayKubeReport
- conn, err := bindings.GetClient(ctx)
- if err != nil {
- return nil, err
- }
-
f, err := os.Open(path)
if err != nil {
return nil, err
@@ -75,7 +75,18 @@ func KubeDown(ctx context.Context, path string) (*entities.PlayKubeReport, error
logrus.Warn(err)
}
}()
- response, err := conn.DoRequest(ctx, f, http.MethodDelete, "/play/kube", nil, nil)
+
+ return KubeDownWithBody(ctx, f)
+}
+
+func KubeDownWithBody(ctx context.Context, body io.Reader) (*entities.PlayKubeReport, error) {
+ var report entities.PlayKubeReport
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := conn.DoRequest(ctx, body, http.MethodDelete, "/play/kube", nil, nil)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/play/types.go b/pkg/bindings/play/types.go
index ca639e46b..dbff4304b 100644
--- a/pkg/bindings/play/types.go
+++ b/pkg/bindings/play/types.go
@@ -7,6 +7,8 @@ import (
//go:generate go run ../generator/generator.go KubeOptions
// KubeOptions are optional options for replaying kube YAML files
type KubeOptions struct {
+ // Annotations - Annotations to add to Pods
+ Annotations map[string]string
// Authfile - path to an authentication file.
Authfile *string
// CertDir - to a directory containing TLS certifications and keys.
diff --git a/pkg/bindings/play/types_kube_options.go b/pkg/bindings/play/types_kube_options.go
index 83a6f1566..d7a452ea2 100644
--- a/pkg/bindings/play/types_kube_options.go
+++ b/pkg/bindings/play/types_kube_options.go
@@ -18,6 +18,21 @@ func (o *KubeOptions) ToParams() (url.Values, error) {
return util.ToParams(o)
}
+// WithAnnotations set field Annotations to given value
+func (o *KubeOptions) WithAnnotations(value map[string]string) *KubeOptions {
+ o.Annotations = value
+ return o
+}
+
+// GetAnnotations returns value of field Annotations
+func (o *KubeOptions) GetAnnotations() map[string]string {
+ if o.Annotations == nil {
+ var z map[string]string
+ return z
+ }
+ return o.Annotations
+}
+
// WithAuthfile set field Authfile to given value
func (o *KubeOptions) WithAuthfile(value string) *KubeOptions {
o.Authfile = &value
diff --git a/pkg/bindings/test/attach_test.go b/pkg/bindings/test/attach_test.go
index 670566882..dcebe0809 100644
--- a/pkg/bindings/test/attach_test.go
+++ b/pkg/bindings/test/attach_test.go
@@ -44,7 +44,8 @@ var _ = Describe("Podman containers attach", func() {
timeout := uint(5)
err := containers.Stop(bt.conn, id, new(containers.StopOptions).WithTimeout(timeout))
if err != nil {
- GinkgoWriter.Write([]byte(err.Error()))
+ _, writeErr := GinkgoWriter.Write([]byte(err.Error()))
+ Expect(writeErr).ShouldNot(HaveOccurred())
}
}()
diff --git a/pkg/bindings/test/auth_test.go b/pkg/bindings/test/auth_test.go
index b421f0797..c4c4b16d8 100644
--- a/pkg/bindings/test/auth_test.go
+++ b/pkg/bindings/test/auth_test.go
@@ -40,7 +40,8 @@ var _ = Describe("Podman images", func() {
AfterEach(func() {
s.Kill()
bt.cleanup()
- registry.Stop()
+ err := registry.Stop()
+ Expect(err).To(BeNil())
})
// Test using credentials.
diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go
index f51e5f404..f2602967b 100644
--- a/pkg/bindings/test/common_test.go
+++ b/pkg/bindings/test/common_test.go
@@ -211,7 +211,7 @@ func (b *bindingTest) RunTopContainer(containerName *string, podName *string) (s
}
ctr, err := containers.CreateWithSpec(b.conn, s, nil)
if err != nil {
- return "", nil
+ return "", err
}
err = containers.Start(b.conn, ctr.ID, nil)
if err != nil {
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
index 9411d8a5f..bf627fdba 100644
--- a/pkg/bindings/test/containers_test.go
+++ b/pkg/bindings/test/containers_test.go
@@ -322,7 +322,8 @@ var _ = Describe("Podman containers ", func() {
// a container that has no healthcheck should be a 409
var name = "top"
- bt.RunTopContainer(&name, nil)
+ _, err = bt.RunTopContainer(&name, nil)
+ Expect(err).To(BeNil())
_, err = containers.RunHealthCheck(bt.conn, name, nil)
Expect(err).ToNot(BeNil())
code, _ = bindings.CheckResponseCode(err)
diff --git a/pkg/checkpoint/crutils/checkpoint_restore_utils.go b/pkg/checkpoint/crutils/checkpoint_restore_utils.go
index 2765d18e8..6a8a7894a 100644
--- a/pkg/checkpoint/crutils/checkpoint_restore_utils.go
+++ b/pkg/checkpoint/crutils/checkpoint_restore_utils.go
@@ -99,13 +99,12 @@ func CRRemoveDeletedFiles(id, baseDirectory, containerRootDirectory string) erro
// root file system changes on top of containerRootDirectory
func CRApplyRootFsDiffTar(baseDirectory, containerRootDirectory string) error {
rootfsDiffPath := filepath.Join(baseDirectory, metadata.RootFsDiffTar)
- if _, err := os.Stat(rootfsDiffPath); err != nil {
- // Only do this if a rootfs-diff.tar actually exists
- return nil
- }
-
+ // Only do this if a rootfs-diff.tar actually exists
rootfsDiffFile, err := os.Open(rootfsDiffPath)
if err != nil {
+ if errors.Is(err, os.ErrNotExist) {
+ return nil
+ }
return errors.Wrap(err, "failed to open root file-system diff file")
}
defer rootfsDiffFile.Close()
diff --git a/pkg/criu/criu.go b/pkg/criu/criu.go
index 967da0dca..b54870abc 100644
--- a/pkg/criu/criu.go
+++ b/pkg/criu/criu.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package criu
diff --git a/pkg/criu/criu_unsupported.go b/pkg/criu/criu_unsupported.go
index 51cd0c1fd..3e3ed9c6c 100644
--- a/pkg/criu/criu_unsupported.go
+++ b/pkg/criu/criu_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package criu
diff --git a/pkg/ctime/ctime_linux.go b/pkg/ctime/ctime_linux.go
index 113693e87..7eb3caa6d 100644
--- a/pkg/ctime/ctime_linux.go
+++ b/pkg/ctime/ctime_linux.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package ctime
diff --git a/pkg/ctime/ctime_unsupported.go b/pkg/ctime/ctime_unsupported.go
index 325731353..afee56027 100644
--- a/pkg/ctime/ctime_unsupported.go
+++ b/pkg/ctime/ctime_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package ctime
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 21272d33f..6b70a3452 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -68,8 +68,8 @@ type ContainerEngine interface {
NetworkPrune(ctx context.Context, options NetworkPruneOptions) ([]*NetworkPruneReport, error)
NetworkReload(ctx context.Context, names []string, options NetworkReloadOptions) ([]*NetworkReloadReport, error)
NetworkRm(ctx context.Context, namesOrIds []string, options NetworkRmOptions) ([]*NetworkRmReport, error)
- PlayKube(ctx context.Context, path string, opts PlayKubeOptions) (*PlayKubeReport, error)
- PlayKubeDown(ctx context.Context, path string, opts PlayKubeDownOptions) (*PlayKubeReport, error)
+ PlayKube(ctx context.Context, body io.Reader, opts PlayKubeOptions) (*PlayKubeReport, error)
+ PlayKubeDown(ctx context.Context, body io.Reader, opts PlayKubeDownOptions) (*PlayKubeReport, error)
PodCreate(ctx context.Context, specg PodSpec) (*PodCreateReport, error)
PodExists(ctx context.Context, nameOrID string) (*BoolReport, error)
PodInspect(ctx context.Context, options PodInspectOptions) (*PodInspectReport, error)
@@ -99,6 +99,8 @@ type ContainerEngine interface {
VolumeMounted(ctx context.Context, namesOrID string) (*BoolReport, error)
VolumeInspect(ctx context.Context, namesOrIds []string, opts InspectOptions) ([]*VolumeInspectReport, []error, error)
VolumeList(ctx context.Context, opts VolumeListOptions) ([]*VolumeListReport, error)
+ VolumeMount(ctx context.Context, namesOrIds []string) ([]*VolumeMountReport, error)
VolumePrune(ctx context.Context, options VolumePruneOptions) ([]*reports.PruneReport, error)
VolumeRm(ctx context.Context, namesOrIds []string, opts VolumeRmOptions) ([]*VolumeRmReport, error)
+ VolumeUnmount(ctx context.Context, namesOrIds []string) ([]*VolumeUnmountReport, error)
}
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index 2ac21cfeb..7081c5d25 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -90,6 +90,8 @@ type ImageRemoveOptions struct {
All bool
// Foce will force image removal including containers using the images.
Force bool
+ // Ignore if a specified image does not exist and do not throw an error.
+ Ignore bool
// Confirms if given name is a manifest list and removes it, otherwise returns error.
LookupManifest bool
}
@@ -277,6 +279,7 @@ type ImageLoadReport struct {
type ImageImportOptions struct {
Architecture string
+ Variant string
Changes []string
Message string
OS string
diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go
index 43fa3a712..c9dc3f08c 100644
--- a/pkg/domain/entities/play.go
+++ b/pkg/domain/entities/play.go
@@ -8,12 +8,16 @@ import (
// PlayKubeOptions controls playing kube YAML files.
type PlayKubeOptions struct {
+ // Annotations - Annotations to add to Pods
+ Annotations map[string]string
// Authfile - path to an authentication file.
Authfile string
// Indicator to build all images with Containerfile or Dockerfile
Build types.OptionalBool
// CertDir - to a directory containing TLS certifications and keys.
CertDir string
+ // ContextDir - directory containing image contexts used for Build
+ ContextDir string
// Down indicates whether to bring contents of a yaml file "down"
// as in stop
Down bool
diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go
index 6fb3db1b5..da93d3f8b 100644
--- a/pkg/domain/entities/pods.go
+++ b/pkg/domain/entities/pods.go
@@ -263,6 +263,7 @@ type ContainerCreateOptions struct {
Workdir string
SeccompPolicy string
PidFile string
+ ChrootDirs []string
IsInfra bool
IsClone bool
diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go
index 4d9ced900..bed3183e9 100644
--- a/pkg/domain/entities/types.go
+++ b/pkg/domain/entities/types.go
@@ -20,7 +20,7 @@ type Volume struct {
}
type Report struct {
- Id []string //nolint
+ Id []string // nolint
Err map[string]error
}
@@ -98,8 +98,10 @@ type EventsOptions struct {
// ContainerCreateResponse is the response struct for creating a container
type ContainerCreateResponse struct {
// ID of the container created
+ // required: true
ID string `json:"Id"`
// Warnings during container creation
+ // required: true
Warnings []string `json:"Warnings"`
}
diff --git a/pkg/domain/entities/volumes.go b/pkg/domain/entities/volumes.go
index 9bdce8392..f2e60a0db 100644
--- a/pkg/domain/entities/volumes.go
+++ b/pkg/domain/entities/volumes.go
@@ -187,3 +187,17 @@ type VolumeCreateBody struct {
// Required: true
Name string `json:"Name"`
}
+
+// VolumeMountReport describes the response from volume mount
+type VolumeMountReport struct {
+ Err error
+ Id string //nolint
+ Name string
+ Path string
+}
+
+// VolumeUnmountReport describes the response from umounting a volume
+type VolumeUnmountReport struct {
+ Err error
+ Id string //nolint
+}
diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go
index 85ba4f84f..4c6964a00 100644
--- a/pkg/domain/filters/containers.go
+++ b/pkg/domain/filters/containers.go
@@ -213,8 +213,10 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
for _, val := range filterValues {
net, err := r.Network().NetworkInspect(val)
if err != nil {
- // ignore not found errors
- break
+ if errors.Is(err, define.ErrNoSuchNetwork) {
+ continue
+ }
+ return nil, err
}
inputNetNames = append(inputNetNames, net.Name)
}
diff --git a/pkg/domain/filters/pods.go b/pkg/domain/filters/pods.go
index 2f9442dff..e22480006 100644
--- a/pkg/domain/filters/pods.go
+++ b/pkg/domain/filters/pods.go
@@ -131,8 +131,10 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti
for _, val := range filterValues {
net, err := r.Network().NetworkInspect(val)
if err != nil {
- // ignore not found errors
- break
+ if errors.Is(err, define.ErrNoSuchNetwork) {
+ continue
+ }
+ return nil, err
}
inputNetNames = append(inputNetNames, net.Name)
}
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index e6feb7c82..1986228a6 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -1431,12 +1431,7 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri
reportStats := []define.ContainerStats{}
for _, ctr := range containers {
- prev, ok := containerStats[ctr.ID()]
- if !ok {
- prev = &define.ContainerStats{}
- }
-
- stats, err := ctr.GetContainerStats(prev)
+ stats, err := ctr.GetContainerStats(containerStats[ctr.ID()])
if err != nil {
cause := errors.Cause(err)
if queryAll && (cause == define.ErrCtrRemoved || cause == define.ErrNoSuchCtr || cause == define.ErrCtrStateInvalid) {
diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go
index cd5ac00b7..ff85dee9b 100644
--- a/pkg/domain/infra/abi/generate.go
+++ b/pkg/domain/infra/abi/generate.go
@@ -9,10 +9,10 @@ import (
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/domain/entities"
+ k8sAPI "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
"github.com/containers/podman/v4/pkg/systemd/generate"
"github.com/ghodss/yaml"
"github.com/pkg/errors"
- k8sAPI "k8s.io/api/core/v1"
)
func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, options entities.GenerateSystemdOptions) (*entities.GenerateSystemdReport, error) {
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 0b1281aac..74478b26d 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -445,7 +445,8 @@ func (ir *ImageEngine) Import(ctx context.Context, options entities.ImageImportO
importOptions.Tag = options.Reference
importOptions.SignaturePolicyPath = options.SignaturePolicy
importOptions.OS = options.OS
- importOptions.Architecture = options.Architecture
+ importOptions.Arch = options.Architecture
+ importOptions.Variant = options.Variant
if !options.Quiet {
importOptions.Writer = os.Stderr
@@ -578,6 +579,7 @@ func (ir *ImageEngine) Remove(ctx context.Context, images []string, opts entitie
libimageOptions := &libimage.RemoveImagesOptions{}
libimageOptions.Filters = []string{"readonly=false"}
libimageOptions.Force = opts.Force
+ libimageOptions.Ignore = opts.Ignore
libimageOptions.LookupManifest = opts.LookupManifest
if !opts.All {
libimageOptions.Filters = append(libimageOptions.Filters, "intermediate=false")
@@ -847,13 +849,12 @@ func execPodman(execUser *user.User, command []string) error {
if err != nil {
return err
}
- defer func() error {
- err := cmdLogin.Process.Kill()
- if err != nil {
- return err
- }
- return cmdLogin.Wait()
+
+ defer func() {
+ _ = cmdLogin.Process.Kill()
+ _ = cmdLogin.Wait()
}()
+
cmd := exec.Command(command[0], command[1:]...)
cmd.Env = []string{"PATH=" + os.Getenv("PATH"), "TERM=" + os.Getenv("TERM")}
cmd.Stderr = os.Stderr
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 8cbf5da9a..1423ab06e 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -20,6 +20,8 @@ import (
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/autoupdate"
"github.com/containers/podman/v4/pkg/domain/entities"
+ v1apps "github.com/containers/podman/v4/pkg/k8s.io/api/apps/v1"
+ v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/pkg/specgen/generate"
"github.com/containers/podman/v4/pkg/specgen/generate/kube"
@@ -28,17 +30,15 @@ import (
"github.com/ghodss/yaml"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
- yamlv3 "gopkg.in/yaml.v3"
- v1apps "k8s.io/api/apps/v1"
- v1 "k8s.io/api/core/v1"
+ yamlv2 "gopkg.in/yaml.v2"
)
-func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
+func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
report := &entities.PlayKubeReport{}
validKinds := 0
// read yaml document
- content, err := ioutil.ReadFile(path)
+ content, err := ioutil.ReadAll(body)
if err != nil {
return nil, err
}
@@ -52,7 +52,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
// sort kube kinds
documentList, err = sortKubeKinds(documentList)
if err != nil {
- return nil, errors.Wrapf(err, "unable to sort kube kinds in %q", path)
+ return nil, errors.Wrap(err, "unable to sort kube kinds")
}
ipIndex := 0
@@ -64,7 +64,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
for _, document := range documentList {
kind, err := getKubeKind(document)
if err != nil {
- return nil, errors.Wrapf(err, "unable to read %q as kube YAML", path)
+ return nil, errors.Wrap(err, "unable to read kube YAML")
}
switch kind {
@@ -73,12 +73,19 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
var podTemplateSpec v1.PodTemplateSpec
if err := yaml.Unmarshal(document, &podYAML); err != nil {
- return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Pod", path)
+ return nil, errors.Wrap(err, "unable to read YAML as Kube Pod")
}
podTemplateSpec.ObjectMeta = podYAML.ObjectMeta
podTemplateSpec.Spec = podYAML.Spec
+ for name, val := range options.Annotations {
+ if podYAML.Annotations == nil {
+ podYAML.Annotations = make(map[string]string)
+ }
+ podYAML.Annotations[name] = val
+ }
+
r, err := ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options, &ipIndex, podYAML.Annotations, configMaps)
if err != nil {
return nil, err
@@ -90,7 +97,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
var deploymentYAML v1apps.Deployment
if err := yaml.Unmarshal(document, &deploymentYAML); err != nil {
- return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path)
+ return nil, errors.Wrap(err, "unable to read YAML as Kube Deployment")
}
r, err := ic.playKubeDeployment(ctx, &deploymentYAML, options, &ipIndex, configMaps)
@@ -104,7 +111,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
var pvcYAML v1.PersistentVolumeClaim
if err := yaml.Unmarshal(document, &pvcYAML); err != nil {
- return nil, errors.Wrapf(err, "unable to read YAML %q as Kube PersistentVolumeClaim", path)
+ return nil, errors.Wrap(err, "unable to read YAML as Kube PersistentVolumeClaim")
}
r, err := ic.playKubePVC(ctx, &pvcYAML, options)
@@ -118,7 +125,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
var configMap v1.ConfigMap
if err := yaml.Unmarshal(document, &configMap); err != nil {
- return nil, errors.Wrapf(err, "unable to read YAML %q as Kube ConfigMap", path)
+ return nil, errors.Wrap(err, "unable to read YAML as Kube ConfigMap")
}
configMaps = append(configMaps, configMap)
default:
@@ -208,7 +215,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
// FIXME This is very hard to support properly with a good ux
if len(options.StaticIPs) > *ipIndex {
if !podOpt.Net.Network.IsBridge() {
- errors.Wrap(define.ErrInvalidArg, "static ip addresses can only be set when the network mode is bridge")
+ return nil, errors.Wrap(define.ErrInvalidArg, "static ip addresses can only be set when the network mode is bridge")
}
if len(podOpt.Net.Networks) != 1 {
return nil, errors.Wrap(define.ErrInvalidArg, "cannot set static ip addresses for more than network, use netname:ip=<ip> syntax to specify ips for more than network")
@@ -223,7 +230,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
}
if len(options.StaticMACs) > *ipIndex {
if !podOpt.Net.Network.IsBridge() {
- errors.Wrap(define.ErrInvalidArg, "static mac address can only be set when the network mode is bridge")
+ return nil, errors.Wrap(define.ErrInvalidArg, "static mac address can only be set when the network mode is bridge")
}
if len(podOpt.Net.Networks) != 1 {
return nil, errors.Wrap(define.ErrInvalidArg, "cannot set static mac address for more than network, use netname:mac=<mac> syntax to specify mac for more than network")
@@ -354,12 +361,24 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
containers := make([]*libpod.Container, 0, len(podYAML.Spec.Containers))
initContainers := make([]*libpod.Container, 0, len(podYAML.Spec.InitContainers))
- cwd, err := os.Getwd()
- if err != nil {
- return nil, err
+
+ var cwd string
+ if options.ContextDir != "" {
+ cwd = options.ContextDir
+ } else {
+ cwd, err = os.Getwd()
+ if err != nil {
+ return nil, err
+ }
}
+ ctrNames := make(map[string]string)
for _, initCtr := range podYAML.Spec.InitContainers {
+ // Error out if same name is used for more than one container
+ if _, ok := ctrNames[initCtr.Name]; ok {
+ return nil, errors.Errorf("the pod %q is invalid; duplicate container name %q detected", podName, initCtr.Name)
+ }
+ ctrNames[initCtr.Name] = ""
// Init containers cannot have either of lifecycle, livenessProbe, readinessProbe, or startupProbe set
if initCtr.Lifecycle != nil || initCtr.LivenessProbe != nil || initCtr.ReadinessProbe != nil || initCtr.StartupProbe != nil {
return nil, errors.Errorf("cannot create an init container that has either of lifecycle, livenessProbe, readinessProbe, or startupProbe set")
@@ -408,6 +427,11 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
}
for _, container := range podYAML.Spec.Containers {
if !strings.Contains("infra", container.Name) {
+ // Error out if the same name is used for more than one container
+ if _, ok := ctrNames[container.Name]; ok {
+ return nil, errors.Errorf("the pod %q is invalid; duplicate container name %q detected", podName, container.Name)
+ }
+ ctrNames[container.Name] = ""
pulledImage, labels, err := ic.getImageAndLabelInfo(ctx, cwd, annotations, writer, container, options)
if err != nil {
return nil, err
@@ -438,6 +462,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
if err != nil {
return nil, err
}
+ specGen.RawImageName = container.Image
rtSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, specGen, false, nil)
if err != nil {
return nil, err
@@ -564,7 +589,7 @@ func (ic *ContainerEngine) playKubePVC(ctx context.Context, pvcYAML *v1.Persiste
// Get pvc name.
// This is the only required pvc attribute to create a podman volume.
- name := pvcYAML.GetName()
+ name := pvcYAML.Name
if strings.TrimSpace(name) == "" {
return nil, fmt.Errorf("persistent volume claim name can not be empty")
}
@@ -572,13 +597,13 @@ func (ic *ContainerEngine) playKubePVC(ctx context.Context, pvcYAML *v1.Persiste
// Create podman volume options.
volOptions := []libpod.VolumeCreateOption{
libpod.WithVolumeName(name),
- libpod.WithVolumeLabels(pvcYAML.GetLabels()),
+ libpod.WithVolumeLabels(pvcYAML.Labels),
}
// Get pvc annotations and create remaining podman volume options if available.
// These are podman volume options that do not match any of the persistent volume claim
// attributes, so they can be configured using annotations since they will not affect k8s.
- for k, v := range pvcYAML.GetAnnotations() {
+ for k, v := range pvcYAML.Annotations {
switch k {
case util.VolumeDriverAnnotation:
volOptions = append(volOptions, libpod.WithVolumeDriver(v))
@@ -644,7 +669,7 @@ func readConfigMapFromFile(r io.Reader) (v1.ConfigMap, error) {
func splitMultiDocYAML(yamlContent []byte) ([][]byte, error) {
var documentList [][]byte
- d := yamlv3.NewDecoder(bytes.NewReader(yamlContent))
+ d := yamlv2.NewDecoder(bytes.NewReader(yamlContent))
for {
var o interface{}
// read individual document
@@ -658,7 +683,7 @@ func splitMultiDocYAML(yamlContent []byte) ([][]byte, error) {
if o != nil {
// back to bytes
- document, err := yamlv3.Marshal(o)
+ document, err := yamlv2.Marshal(o)
if err != nil {
return nil, errors.Wrapf(err, "individual doc yaml could not be marshalled")
}
@@ -748,14 +773,14 @@ func getBuildFile(imageName string, cwd string) (string, error) {
return "", err
}
-func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, path string, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) {
+func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, body io.Reader, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) {
var (
podNames []string
)
reports := new(entities.PlayKubeReport)
// read yaml document
- content, err := ioutil.ReadFile(path)
+ content, err := ioutil.ReadAll(body)
if err != nil {
return nil, err
}
@@ -769,27 +794,27 @@ func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, path string, _ enti
// sort kube kinds
documentList, err = sortKubeKinds(documentList)
if err != nil {
- return nil, errors.Wrapf(err, "unable to sort kube kinds in %q", path)
+ return nil, errors.Wrap(err, "unable to sort kube kinds")
}
for _, document := range documentList {
kind, err := getKubeKind(document)
if err != nil {
- return nil, errors.Wrapf(err, "unable to read %q as kube YAML", path)
+ return nil, errors.Wrap(err, "unable to read as kube YAML")
}
switch kind {
case "Pod":
var podYAML v1.Pod
if err := yaml.Unmarshal(document, &podYAML); err != nil {
- return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Pod", path)
+ return nil, errors.Wrap(err, "unable to read YAML as Kube Pod")
}
podNames = append(podNames, podYAML.ObjectMeta.Name)
case "Deployment":
var deploymentYAML v1apps.Deployment
if err := yaml.Unmarshal(document, &deploymentYAML); err != nil {
- return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path)
+ return nil, errors.Wrap(err, "unable to read YAML as Kube Deployment")
}
var numReplicas int32 = 1
deploymentName := deploymentYAML.ObjectMeta.Name
diff --git a/pkg/domain/infra/abi/play_test.go b/pkg/domain/infra/abi/play_test.go
index bbc7c3493..e11581fa2 100644
--- a/pkg/domain/infra/abi/play_test.go
+++ b/pkg/domain/infra/abi/play_test.go
@@ -4,9 +4,9 @@ import (
"bytes"
"testing"
+ v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
+ v12 "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/stretchr/testify/assert"
- v1 "k8s.io/api/core/v1"
- v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestReadConfigMapFromFile(t *testing.T) {
diff --git a/pkg/domain/infra/abi/terminal/sigproxy_linux.go b/pkg/domain/infra/abi/terminal/sigproxy_linux.go
index 206ded091..fe2c268c0 100644
--- a/pkg/domain/infra/abi/terminal/sigproxy_linux.go
+++ b/pkg/domain/infra/abi/terminal/sigproxy_linux.go
@@ -20,7 +20,7 @@ const signalBufferSize = 2048
func ProxySignals(ctr *libpod.Container) {
// Stop catching the shutdown signals (SIGINT, SIGTERM) - they're going
// to the container now.
- shutdown.Stop()
+ shutdown.Stop() // nolint: errcheck
sigBuffer := make(chan os.Signal, signalBufferSize)
signal.CatchAll(sigBuffer)
diff --git a/pkg/domain/infra/abi/terminal/terminal_linux.go b/pkg/domain/infra/abi/terminal/terminal_linux.go
index 78c792d2b..153b19fdb 100644
--- a/pkg/domain/infra/abi/terminal/terminal_linux.go
+++ b/pkg/domain/infra/abi/terminal/terminal_linux.go
@@ -39,7 +39,7 @@ func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpo
// StartAttachCtr starts and (if required) attaches to a container
// if you change the signature of this function from os.File to io.Writer, it will trigger a downstream
// error. we may need to just lint disable this one.
-func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool) error { //nolint-interfacer
+func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool) error { //nolint: interfacer
resize := make(chan define.TerminalSize)
haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd()))
diff --git a/pkg/domain/infra/abi/volumes.go b/pkg/domain/infra/abi/volumes.go
index ee7269807..f59f11e20 100644
--- a/pkg/domain/infra/abi/volumes.go
+++ b/pkg/domain/infra/abi/volumes.go
@@ -171,10 +171,43 @@ func (ic *ContainerEngine) VolumeMounted(ctx context.Context, nameOrID string) (
}
mountCount, err := vol.MountCount()
if err != nil {
- return &entities.BoolReport{Value: false}, nil
+ // FIXME: this error should probably be returned
+ return &entities.BoolReport{Value: false}, nil // nolint: nilerr
}
if mountCount > 0 {
return &entities.BoolReport{Value: true}, nil
}
return &entities.BoolReport{Value: false}, nil
}
+
+func (ic *ContainerEngine) VolumeMount(ctx context.Context, nameOrIDs []string) ([]*entities.VolumeMountReport, error) {
+ reports := []*entities.VolumeMountReport{}
+ for _, name := range nameOrIDs {
+ report := entities.VolumeMountReport{Id: name}
+ vol, err := ic.Libpod.LookupVolume(name)
+ if err != nil {
+ report.Err = err
+ } else {
+ report.Path, report.Err = vol.Mount()
+ }
+ reports = append(reports, &report)
+ }
+
+ return reports, nil
+}
+
+func (ic *ContainerEngine) VolumeUnmount(ctx context.Context, nameOrIDs []string) ([]*entities.VolumeUnmountReport, error) {
+ reports := []*entities.VolumeUnmountReport{}
+ for _, name := range nameOrIDs {
+ report := entities.VolumeUnmountReport{Id: name}
+ vol, err := ic.Libpod.LookupVolume(name)
+ if err != nil {
+ report.Err = err
+ } else {
+ report.Err = vol.Unmount()
+ }
+ reports = append(reports, &report)
+ }
+
+ return reports, nil
+}
diff --git a/pkg/domain/infra/runtime_abi.go b/pkg/domain/infra/runtime_abi.go
index 5b7b7cf8a..39989c96b 100644
--- a/pkg/domain/infra/runtime_abi.go
+++ b/pkg/domain/infra/runtime_abi.go
@@ -1,3 +1,4 @@
+//go:build !remote
// +build !remote
package infra
diff --git a/pkg/domain/infra/runtime_abi_unsupported.go b/pkg/domain/infra/runtime_abi_unsupported.go
index b4414dc54..9e5bd01eb 100644
--- a/pkg/domain/infra/runtime_abi_unsupported.go
+++ b/pkg/domain/infra/runtime_abi_unsupported.go
@@ -1,3 +1,4 @@
+//go:build remote
// +build remote
package infra
diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go
index f9ceb9305..dffd90dbe 100644
--- a/pkg/domain/infra/runtime_libpod.go
+++ b/pkg/domain/infra/runtime_libpod.go
@@ -1,3 +1,4 @@
+//go:build !remote
// +build !remote
package infra
diff --git a/pkg/domain/infra/runtime_proxy.go b/pkg/domain/infra/runtime_proxy.go
index a70b61165..e5761d4ab 100644
--- a/pkg/domain/infra/runtime_proxy.go
+++ b/pkg/domain/infra/runtime_proxy.go
@@ -1,3 +1,4 @@
+//go:build !remote
// +build !remote
package infra
diff --git a/pkg/domain/infra/runtime_tunnel.go b/pkg/domain/infra/runtime_tunnel.go
index 68f8b0dac..8a4de032f 100644
--- a/pkg/domain/infra/runtime_tunnel.go
+++ b/pkg/domain/infra/runtime_tunnel.go
@@ -1,3 +1,4 @@
+//go:build remote
// +build remote
package infra
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index fe986361b..10bfb3984 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -390,7 +390,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
options.WithPublishPorts(opts.PublishPorts)
if opts.Import != "" {
- options.WithImportAchive(opts.Import)
+ options.WithImportArchive(opts.Import)
report, err := containers.Restore(ic.ClientCtx, "", options)
return []*entities.RestoreReport{report}, err
}
@@ -840,7 +840,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
if eventsErr != nil || lastEvent == nil {
logrus.Errorf("Cannot get exit code: %v", err)
report.ExitCode = define.ExecErrorCodeNotFound
- return &report, nil // compat with local client
+ return &report, nil // nolint: nilerr
}
report.ExitCode = lastEvent.ContainerExitCode
@@ -938,7 +938,7 @@ func (ic *ContainerEngine) ContainerStat(ctx context.Context, nameOrID string, p
return containers.Stat(ic.ClientCtx, nameOrID, path)
}
-// Shutdown Libpod engine
+// Shutdown Libpod engine.
func (ic *ContainerEngine) Shutdown(_ context.Context) {
}
@@ -949,7 +949,7 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri
return containers.Stats(ic.ClientCtx, namesOrIds, new(containers.StatsOptions).WithStream(options.Stream).WithInterval(options.Interval))
}
-// ShouldRestart reports back whether the container will restart
+// ShouldRestart reports back whether the container will restart.
func (ic *ContainerEngine) ShouldRestart(_ context.Context, id string) (bool, error) {
return containers.ShouldRestart(ic.ClientCtx, id, nil)
}
diff --git a/pkg/domain/infra/tunnel/events.go b/pkg/domain/infra/tunnel/events.go
index 1f27cdff8..b472ad03a 100644
--- a/pkg/domain/infra/tunnel/events.go
+++ b/pkg/domain/infra/tunnel/events.go
@@ -34,7 +34,7 @@ func (ic *ContainerEngine) Events(ctx context.Context, opts entities.EventsOptio
}
// GetLastContainerEvent takes a container name or ID and an event status and returns
-// the last occurrence of the container event
+// the last occurrence of the container event.
func (ic *ContainerEngine) GetLastContainerEvent(ctx context.Context, nameOrID string, containerEvent events.Status) (*events.Event, error) {
// check to make sure the event.Status is valid
if _, err := events.StringToStatus(containerEvent.String()); err != nil {
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 3ee97d94c..18e10e8dd 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -28,7 +28,7 @@ func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.Boo
}
func (ir *ImageEngine) Remove(ctx context.Context, imagesArg []string, opts entities.ImageRemoveOptions) (*entities.ImageRemoveReport, []error) {
- options := new(images.RemoveOptions).WithForce(opts.Force).WithAll(opts.All)
+ options := new(images.RemoveOptions).WithForce(opts.Force).WithIgnore(opts.Ignore).WithAll(opts.All)
return images.Remove(ir.ClientCtx, imagesArg, options)
}
@@ -230,6 +230,7 @@ func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOpti
f *os.File
)
options := new(images.ImportOptions).WithChanges(opts.Changes).WithMessage(opts.Message).WithReference(opts.Reference)
+ options.WithOS(opts.OS).WithArchitecture(opts.Architecture).WithVariant(opts.Variant)
if opts.SourceIsURL {
options.WithURL(opts.Source)
} else {
diff --git a/pkg/domain/infra/tunnel/play.go b/pkg/domain/infra/tunnel/play.go
index 55844730b..d9637254a 100644
--- a/pkg/domain/infra/tunnel/play.go
+++ b/pkg/domain/infra/tunnel/play.go
@@ -2,13 +2,14 @@ package tunnel
import (
"context"
+ "io"
"github.com/containers/image/v5/types"
"github.com/containers/podman/v4/pkg/bindings/play"
"github.com/containers/podman/v4/pkg/domain/entities"
)
-func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, opts entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
+func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, opts entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
options := new(play.KubeOptions).WithAuthfile(opts.Authfile).WithUsername(opts.Username).WithPassword(opts.Password)
options.WithCertDir(opts.CertDir).WithQuiet(opts.Quiet).WithSignaturePolicy(opts.SignaturePolicy).WithConfigMaps(opts.ConfigMaps)
options.WithLogDriver(opts.LogDriver).WithNetwork(opts.Networks).WithSeccompProfileRoot(opts.SeccompProfileRoot)
@@ -16,6 +17,9 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, opts entit
if len(opts.LogOptions) > 0 {
options.WithLogOptions(opts.LogOptions)
}
+ if opts.Annotations != nil {
+ options.WithAnnotations(opts.Annotations)
+ }
options.WithNoHosts(opts.NoHosts)
if s := opts.SkipTLSVerify; s != types.OptionalBoolUndefined {
options.WithSkipTLSVerify(s == types.OptionalBoolTrue)
@@ -23,9 +27,9 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, opts entit
if start := opts.Start; start != types.OptionalBoolUndefined {
options.WithStart(start == types.OptionalBoolTrue)
}
- return play.Kube(ic.ClientCtx, path, options)
+ return play.KubeWithBody(ic.ClientCtx, body, options)
}
-func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, path string, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) {
- return play.KubeDown(ic.ClientCtx, path)
+func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, body io.Reader, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) {
+ return play.KubeDownWithBody(ic.ClientCtx, body)
}
diff --git a/pkg/domain/infra/tunnel/volumes.go b/pkg/domain/infra/tunnel/volumes.go
index f4abeab0f..33e090148 100644
--- a/pkg/domain/infra/tunnel/volumes.go
+++ b/pkg/domain/infra/tunnel/volumes.go
@@ -100,3 +100,11 @@ func (ic *ContainerEngine) VolumeExists(ctx context.Context, nameOrID string) (*
func (ic *ContainerEngine) VolumeMounted(ctx context.Context, nameOrID string) (*entities.BoolReport, error) {
return nil, errors.New("not implemented")
}
+
+func (ic *ContainerEngine) VolumeMount(ctx context.Context, nameOrIDs []string) ([]*entities.VolumeMountReport, error) {
+ return nil, errors.New("mounting volumes is not supported for remote clients")
+}
+
+func (ic *ContainerEngine) VolumeUnmount(ctx context.Context, nameOrIDs []string) ([]*entities.VolumeUnmountReport, error) {
+ return nil, errors.New("unmounting volumes is not supported for remote clients")
+}
diff --git a/pkg/env/env.go b/pkg/env/env.go
index ecd2d62a5..5989d0da5 100644
--- a/pkg/env/env.go
+++ b/pkg/env/env.go
@@ -26,7 +26,7 @@ func DefaultEnvVariables() map[string]string {
// Slice transforms the specified map of environment variables into a
// slice. If a value is non-empty, the key and value are joined with '='.
func Slice(m map[string]string) []string {
- env := make([]string, len(m))
+ env := make([]string, 0, len(m))
for k, v := range m {
var s string
if len(v) > 0 {
diff --git a/pkg/env/env_unix.go b/pkg/env/env_unix.go
index 16061a700..690078f33 100644
--- a/pkg/env/env_unix.go
+++ b/pkg/env/env_unix.go
@@ -1,3 +1,4 @@
+//go:build !windows
// +build !windows
package env
diff --git a/pkg/errorhandling/errorhandling.go b/pkg/errorhandling/errorhandling.go
index 04110b62a..e33c26032 100644
--- a/pkg/errorhandling/errorhandling.go
+++ b/pkg/errorhandling/errorhandling.go
@@ -28,7 +28,7 @@ func JoinErrors(errs []error) error {
finalErr := multiE.ErrorOrNil()
if finalErr == nil {
- return finalErr
+ return nil
}
return errors.New(strings.TrimSpace(finalErr.Error()))
}
diff --git a/pkg/inspect/inspect.go b/pkg/inspect/inspect.go
index cd26db6b0..767d86daf 100644
--- a/pkg/inspect/inspect.go
+++ b/pkg/inspect/inspect.go
@@ -9,7 +9,7 @@ import (
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)
-// ImageData holds the inspect information of an image
+// ImageData holds the inspect information of an image.
type ImageData struct {
ID string `json:"Id"`
Digest digest.Digest `json:"Digest"`
@@ -36,13 +36,13 @@ type ImageData struct {
HealthCheck *manifest.Schema2HealthConfig `json:"Healthcheck,omitempty"`
}
-// RootFS holds the root fs information of an image
+// RootFS holds the root fs information of an image.
type RootFS struct {
Type string `json:"Type"`
Layers []digest.Digest `json:"Layers"`
}
-// ImageResult is used for podman images for collection and output
+// ImageResult is used for podman images for collection and output.
type ImageResult struct {
Tag string
Repository string
diff --git a/pkg/k8s.io/README.md b/pkg/k8s.io/README.md
new file mode 100644
index 000000000..5594ce6c5
--- /dev/null
+++ b/pkg/k8s.io/README.md
@@ -0,0 +1,6 @@
+The code in this directory was copied from Kubernetes version 0.22.5:
+ - https://github.com/kubernetes/apimachinery/tree/v0.22.5
+ - https://github.com/kubernetes/api/tree/v0.22.5
+
+The code is heavily modified by the Podman team (mostly removing unneeded code) to reduce the resulting binary size.
+The copyright belongs to the Kubernetes Authors and is licensed under Apache-2.0, also check the license headers in the files.
diff --git a/pkg/k8s.io/api/LICENSE b/pkg/k8s.io/api/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/pkg/k8s.io/api/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/pkg/k8s.io/api/apps/v1/types.go b/pkg/k8s.io/api/apps/v1/types.go
new file mode 100644
index 000000000..3be9f6dbd
--- /dev/null
+++ b/pkg/k8s.io/api/apps/v1/types.go
@@ -0,0 +1,831 @@
+/*
+Copyright 2017 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1
+
+import (
+ v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
+ metav1 "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/apis/meta/v1"
+ "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/util/intstr"
+)
+
+const (
+ ControllerRevisionHashLabelKey = "controller-revision-hash"
+ StatefulSetRevisionLabel = ControllerRevisionHashLabelKey
+ DeprecatedRollbackTo = "deprecated.deployment.rollback.to"
+ DeprecatedTemplateGeneration = "deprecated.daemonset.template.generation"
+ StatefulSetPodNameLabel = "statefulset.kubernetes.io/pod-name"
+)
+
+// +genclient
+// +genclient:method=GetScale,verb=get,subresource=scale,result=k8s.io/api/autoscaling/v1.Scale
+// +genclient:method=UpdateScale,verb=update,subresource=scale,input=k8s.io/api/autoscaling/v1.Scale,result=k8s.io/api/autoscaling/v1.Scale
+// +genclient:method=ApplyScale,verb=apply,subresource=scale,input=k8s.io/api/autoscaling/v1.Scale,result=k8s.io/api/autoscaling/v1.Scale
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// StatefulSet represents a set of pods with consistent identities.
+// Identities are defined as:
+// - Network: A single stable DNS and hostname.
+// - Storage: As many VolumeClaims as requested.
+// The StatefulSet guarantees that a given network identity will always
+// map to the same storage identity.
+type StatefulSet struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Spec defines the desired identities of pods in this set.
+ // +optional
+ Spec StatefulSetSpec `json:"spec,omitempty"`
+
+ // Status is the current status of Pods in this StatefulSet. This data
+ // may be out of date by some window of time.
+ // +optional
+ Status StatefulSetStatus `json:"status,omitempty"`
+}
+
+// PodManagementPolicyType defines the policy for creating pods under a stateful set.
+type PodManagementPolicyType string
+
+const (
+ // OrderedReadyPodManagement will create pods in strictly increasing order on
+ // scale up and strictly decreasing order on scale down, progressing only when
+ // the previous pod is ready or terminated. At most one pod will be changed
+ // at any time.
+ OrderedReadyPodManagement PodManagementPolicyType = "OrderedReady"
+ // ParallelPodManagement will create and delete pods as soon as the stateful set
+ // replica count is changed, and will not wait for pods to be ready or complete
+ // termination.
+ ParallelPodManagement PodManagementPolicyType = "Parallel"
+)
+
+// StatefulSetUpdateStrategy indicates the strategy that the StatefulSet
+// controller will use to perform updates. It includes any additional parameters
+// necessary to perform the update for the indicated strategy.
+type StatefulSetUpdateStrategy struct {
+ // Type indicates the type of the StatefulSetUpdateStrategy.
+ // Default is RollingUpdate.
+ // +optional
+ Type StatefulSetUpdateStrategyType `json:"type,omitempty"`
+ // RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType.
+ // +optional
+ RollingUpdate *RollingUpdateStatefulSetStrategy `json:"rollingUpdate,omitempty"`
+}
+
+// StatefulSetUpdateStrategyType is a string enumeration type that enumerates
+// all possible update strategies for the StatefulSet controller.
+type StatefulSetUpdateStrategyType string
+
+const (
+ // RollingUpdateStatefulSetStrategyType indicates that update will be
+ // applied to all Pods in the StatefulSet with respect to the StatefulSet
+ // ordering constraints. When a scale operation is performed with this
+ // strategy, new Pods will be created from the specification version indicated
+ // by the StatefulSet's updateRevision.
+ RollingUpdateStatefulSetStrategyType StatefulSetUpdateStrategyType = "RollingUpdate"
+ // OnDeleteStatefulSetStrategyType triggers the legacy behavior. Version
+ // tracking and ordered rolling restarts are disabled. Pods are recreated
+ // from the StatefulSetSpec when they are manually deleted. When a scale
+ // operation is performed with this strategy,specification version indicated
+ // by the StatefulSet's currentRevision.
+ OnDeleteStatefulSetStrategyType StatefulSetUpdateStrategyType = "OnDelete"
+)
+
+// RollingUpdateStatefulSetStrategy is used to communicate parameter for RollingUpdateStatefulSetStrategyType.
+type RollingUpdateStatefulSetStrategy struct {
+ // Partition indicates the ordinal at which the StatefulSet should be
+ // partitioned.
+ // Default value is 0.
+ // +optional
+ Partition *int32 `json:"partition,omitempty"`
+}
+
+// A StatefulSetSpec is the specification of a StatefulSet.
+type StatefulSetSpec struct {
+ // replicas is the desired number of replicas of the given Template.
+ // These are replicas in the sense that they are instantiations of the
+ // same Template, but individual replicas also have a consistent identity.
+ // If unspecified, defaults to 1.
+ // TODO: Consider a rename of this field.
+ // +optional
+ Replicas *int32 `json:"replicas,omitempty"`
+
+ // selector is a label query over pods that should match the replica count.
+ // It must match the pod template's labels.
+ // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
+ Selector *metav1.LabelSelector `json:"selector"`
+
+ // template is the object that describes the pod that will be created if
+ // insufficient replicas are detected. Each pod stamped out by the StatefulSet
+ // will fulfill this Template, but have a unique identity from the rest
+ // of the StatefulSet.
+ Template v1.PodTemplateSpec `json:"template"`
+
+ // volumeClaimTemplates is a list of claims that pods are allowed to reference.
+ // The StatefulSet controller is responsible for mapping network identities to
+ // claims in a way that maintains the identity of a pod. Every claim in
+ // this list must have at least one matching (by name) volumeMount in one
+ // container in the template. A claim in this list takes precedence over
+ // any volumes in the template, with the same name.
+ // TODO: Define the behavior if a claim already exists with the same name.
+ // +optional
+ VolumeClaimTemplates []v1.PersistentVolumeClaim `json:"volumeClaimTemplates,omitempty"`
+
+ // serviceName is the name of the service that governs this StatefulSet.
+ // This service must exist before the StatefulSet, and is responsible for
+ // the network identity of the set. Pods get DNS/hostnames that follow the
+ // pattern: pod-specific-string.serviceName.default.svc.cluster.local
+ // where "pod-specific-string" is managed by the StatefulSet controller.
+ ServiceName string `json:"serviceName"`
+
+ // podManagementPolicy controls how pods are created during initial scale up,
+ // when replacing pods on nodes, or when scaling down. The default policy is
+ // `OrderedReady`, where pods are created in increasing order (pod-0, then
+ // pod-1, etc) and the controller will wait until each pod is ready before
+ // continuing. When scaling down, the pods are removed in the opposite order.
+ // The alternative policy is `Parallel` which will create pods in parallel
+ // to match the desired scale without waiting, and on scale down will delete
+ // all pods at once.
+ // +optional
+ PodManagementPolicy PodManagementPolicyType `json:"podManagementPolicy,omitempty"`
+
+ // updateStrategy indicates the StatefulSetUpdateStrategy that will be
+ // employed to update Pods in the StatefulSet when a revision is made to
+ // Template.
+ UpdateStrategy StatefulSetUpdateStrategy `json:"updateStrategy,omitempty"`
+
+ // revisionHistoryLimit is the maximum number of revisions that will
+ // be maintained in the StatefulSet's revision history. The revision history
+ // consists of all revisions not represented by a currently applied
+ // StatefulSetSpec version. The default value is 10.
+ RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty"`
+
+ // Minimum number of seconds for which a newly created pod should be ready
+ // without any of its container crashing for it to be considered available.
+ // Defaults to 0 (pod will be considered available as soon as it is ready)
+ // This is an alpha field and requires enabling StatefulSetMinReadySeconds feature gate.
+ // +optional
+ MinReadySeconds int32 `json:"minReadySeconds,omitempty"`
+}
+
+// StatefulSetStatus represents the current state of a StatefulSet.
+type StatefulSetStatus struct {
+ // observedGeneration is the most recent generation observed for this StatefulSet. It corresponds to the
+ // StatefulSet's generation, which is updated on mutation by the API Server.
+ // +optional
+ ObservedGeneration int64 `json:"observedGeneration,omitempty"`
+
+ // replicas is the number of Pods created by the StatefulSet controller.
+ Replicas int32 `json:"replicas"`
+
+ // readyReplicas is the number of Pods created by the StatefulSet controller that have a Ready Condition.
+ ReadyReplicas int32 `json:"readyReplicas,omitempty"`
+
+ // currentReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version
+ // indicated by currentRevision.
+ CurrentReplicas int32 `json:"currentReplicas,omitempty"`
+
+ // updatedReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version
+ // indicated by updateRevision.
+ UpdatedReplicas int32 `json:"updatedReplicas,omitempty"`
+
+ // currentRevision, if not empty, indicates the version of the StatefulSet used to generate Pods in the
+ // sequence [0,currentReplicas).
+ CurrentRevision string `json:"currentRevision,omitempty"`
+
+ // updateRevision, if not empty, indicates the version of the StatefulSet used to generate Pods in the sequence
+ // [replicas-updatedReplicas,replicas)
+ UpdateRevision string `json:"updateRevision,omitempty"`
+
+ // collisionCount is the count of hash collisions for the StatefulSet. The StatefulSet controller
+ // uses this field as a collision avoidance mechanism when it needs to create the name for the
+ // newest ControllerRevision.
+ // +optional
+ CollisionCount *int32 `json:"collisionCount,omitempty"`
+
+ // Represents the latest available observations of a statefulset's current state.
+ // +optional
+ // +patchMergeKey=type
+ // +patchStrategy=merge
+ Conditions []StatefulSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
+
+ // Total number of available pods (ready for at least minReadySeconds) targeted by this statefulset.
+ // This is an alpha field and requires enabling StatefulSetMinReadySeconds feature gate.
+ // Remove omitempty when graduating to beta
+ // +optional
+ AvailableReplicas int32 `json:"availableReplicas,omitempty"`
+}
+
+type StatefulSetConditionType string
+
+// StatefulSetCondition describes the state of a statefulset at a certain point.
+type StatefulSetCondition struct {
+ // Type of statefulset condition.
+ Type StatefulSetConditionType `json:"type"`
+ // Status of the condition, one of True, False, Unknown.
+ Status v1.ConditionStatus `json:"status"`
+ // Last time the condition transitioned from one status to another.
+ // +optional
+ LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
+ // The reason for the condition's last transition.
+ // +optional
+ Reason string `json:"reason,omitempty"`
+ // A human readable message indicating details about the transition.
+ // +optional
+ Message string `json:"message,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// StatefulSetList is a collection of StatefulSets.
+type StatefulSetList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // Items is the list of stateful sets.
+ Items []StatefulSet `json:"items"`
+}
+
+// +genclient
+// +genclient:method=GetScale,verb=get,subresource=scale,result=k8s.io/api/autoscaling/v1.Scale
+// +genclient:method=UpdateScale,verb=update,subresource=scale,input=k8s.io/api/autoscaling/v1.Scale,result=k8s.io/api/autoscaling/v1.Scale
+// +genclient:method=ApplyScale,verb=apply,subresource=scale,input=k8s.io/api/autoscaling/v1.Scale,result=k8s.io/api/autoscaling/v1.Scale
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// Deployment enables declarative updates for Pods and ReplicaSets.
+type Deployment struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Specification of the desired behavior of the Deployment.
+ // +optional
+ Spec DeploymentSpec `json:"spec,omitempty"`
+
+ // Most recently observed status of the Deployment.
+ // +optional
+ Status DeploymentStatus `json:"status,omitempty"`
+}
+
+// DeploymentSpec is the specification of the desired behavior of the Deployment.
+type DeploymentSpec struct {
+ // Number of desired pods. This is a pointer to distinguish between explicit
+ // zero and not specified. Defaults to 1.
+ // +optional
+ Replicas *int32 `json:"replicas,omitempty"`
+
+ // Label selector for pods. Existing ReplicaSets whose pods are
+ // selected by this will be the ones affected by this deployment.
+ // It must match the pod template's labels.
+ Selector *metav1.LabelSelector `json:"selector"`
+
+ // Template describes the pods that will be created.
+ Template v1.PodTemplateSpec `json:"template"`
+
+ // The deployment strategy to use to replace existing pods with new ones.
+ // +optional
+ // +patchStrategy=retainKeys
+ Strategy DeploymentStrategy `json:"strategy,omitempty" patchStrategy:"retainKeys"`
+
+ // Minimum number of seconds for which a newly created pod should be ready
+ // without any of its container crashing, for it to be considered available.
+ // Defaults to 0 (pod will be considered available as soon as it is ready)
+ // +optional
+ MinReadySeconds int32 `json:"minReadySeconds,omitempty"`
+
+ // The number of old ReplicaSets to retain to allow rollback.
+ // This is a pointer to distinguish between explicit zero and not specified.
+ // Defaults to 10.
+ // +optional
+ RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty"`
+
+ // Indicates that the deployment is paused.
+ // +optional
+ Paused bool `json:"paused,omitempty"`
+
+ // The maximum time in seconds for a deployment to make progress before it
+ // is considered to be failed. The deployment controller will continue to
+ // process failed deployments and a condition with a ProgressDeadlineExceeded
+ // reason will be surfaced in the deployment status. Note that progress will
+ // not be estimated during the time a deployment is paused. Defaults to 600s.
+ ProgressDeadlineSeconds *int32 `json:"progressDeadlineSeconds,omitempty"`
+}
+
+const (
+ // DefaultDeploymentUniqueLabelKey is the default key of the selector that is added
+ // to existing ReplicaSets (and label key that is added to its pods) to prevent the existing ReplicaSets
+ // to select new pods (and old pods being select by new ReplicaSet).
+ DefaultDeploymentUniqueLabelKey string = "pod-template-hash"
+)
+
+// DeploymentStrategy describes how to replace existing pods with new ones.
+type DeploymentStrategy struct {
+ // Type of deployment. Can be "Recreate" or "RollingUpdate". Default is RollingUpdate.
+ // +optional
+ Type DeploymentStrategyType `json:"type,omitempty"`
+
+ // Rolling update config params. Present only if DeploymentStrategyType =
+ // RollingUpdate.
+ //---
+ // TODO: Update this to follow our convention for oneOf, whatever we decide it
+ // to be.
+ // +optional
+ RollingUpdate *RollingUpdateDeployment `json:"rollingUpdate,omitempty"`
+}
+
+type DeploymentStrategyType string
+
+const (
+ // Kill all existing pods before creating new ones.
+ RecreateDeploymentStrategyType DeploymentStrategyType = "Recreate"
+
+ // Replace the old ReplicaSets by new one using rolling update i.e gradually scale down the old ReplicaSets and scale up the new one.
+ RollingUpdateDeploymentStrategyType DeploymentStrategyType = "RollingUpdate"
+)
+
+// Spec to control the desired behavior of rolling update.
+type RollingUpdateDeployment struct {
+ // The maximum number of pods that can be unavailable during the update.
+ // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
+ // Absolute number is calculated from percentage by rounding down.
+ // This can not be 0 if MaxSurge is 0.
+ // Defaults to 25%.
+ // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods
+ // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet
+ // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring
+ // that the total number of pods available at all times during the update is at
+ // least 70% of desired pods.
+ // +optional
+ MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"`
+
+ // The maximum number of pods that can be scheduled above the desired number of
+ // pods.
+ // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
+ // This can not be 0 if MaxUnavailable is 0.
+ // Absolute number is calculated from percentage by rounding up.
+ // Defaults to 25%.
+ // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when
+ // the rolling update starts, such that the total number of old and new pods do not exceed
+ // 130% of desired pods. Once old pods have been killed,
+ // new ReplicaSet can be scaled up further, ensuring that total number of pods running
+ // at any time during the update is at most 130% of desired pods.
+ // +optional
+ MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty"`
+}
+
+// DeploymentStatus is the most recently observed status of the Deployment.
+type DeploymentStatus struct {
+ // The generation observed by the deployment controller.
+ // +optional
+ ObservedGeneration int64 `json:"observedGeneration,omitempty"`
+
+ // Total number of non-terminated pods targeted by this deployment (their labels match the selector).
+ // +optional
+ Replicas int32 `json:"replicas,omitempty"`
+
+ // Total number of non-terminated pods targeted by this deployment that have the desired template spec.
+ // +optional
+ UpdatedReplicas int32 `json:"updatedReplicas,omitempty"`
+
+ // Total number of ready pods targeted by this deployment.
+ // +optional
+ ReadyReplicas int32 `json:"readyReplicas,omitempty"`
+
+ // Total number of available pods (ready for at least minReadySeconds) targeted by this deployment.
+ // +optional
+ AvailableReplicas int32 `json:"availableReplicas,omitempty"`
+
+ // Total number of unavailable pods targeted by this deployment. This is the total number of
+ // pods that are still required for the deployment to have 100% available capacity. They may
+ // either be pods that are running but not yet available or pods that still have not been created.
+ // +optional
+ UnavailableReplicas int32 `json:"unavailableReplicas,omitempty"`
+
+ // Represents the latest available observations of a deployment's current state.
+ // +patchMergeKey=type
+ // +patchStrategy=merge
+ Conditions []DeploymentCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
+
+ // Count of hash collisions for the Deployment. The Deployment controller uses this
+ // field as a collision avoidance mechanism when it needs to create the name for the
+ // newest ReplicaSet.
+ // +optional
+ CollisionCount *int32 `json:"collisionCount,omitempty"`
+}
+
+type DeploymentConditionType string
+
+// These are valid conditions of a deployment.
+const (
+ // Available means the deployment is available, ie. at least the minimum available
+ // replicas required are up and running for at least minReadySeconds.
+ DeploymentAvailable DeploymentConditionType = "Available"
+ // Progressing means the deployment is progressing. Progress for a deployment is
+ // considered when a new replica set is created or adopted, and when new pods scale
+ // up or old pods scale down. Progress is not estimated for paused deployments or
+ // when progressDeadlineSeconds is not specified.
+ DeploymentProgressing DeploymentConditionType = "Progressing"
+ // ReplicaFailure is added in a deployment when one of its pods fails to be created
+ // or deleted.
+ DeploymentReplicaFailure DeploymentConditionType = "ReplicaFailure"
+)
+
+// DeploymentCondition describes the state of a deployment at a certain point.
+type DeploymentCondition struct {
+ // Type of deployment condition.
+ Type DeploymentConditionType `json:"type"`
+ // Status of the condition, one of True, False, Unknown.
+ Status v1.ConditionStatus `json:"status"`
+ // The last time this condition was updated.
+ LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"`
+ // Last time the condition transitioned from one status to another.
+ LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
+ // The reason for the condition's last transition.
+ Reason string `json:"reason,omitempty"`
+ // A human readable message indicating details about the transition.
+ Message string `json:"message,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// DeploymentList is a list of Deployments.
+type DeploymentList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // Items is the list of Deployments.
+ Items []Deployment `json:"items"`
+}
+
+// DaemonSetUpdateStrategy is a struct used to control the update strategy for a DaemonSet.
+type DaemonSetUpdateStrategy struct {
+ // Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is RollingUpdate.
+ // +optional
+ Type DaemonSetUpdateStrategyType `json:"type,omitempty"`
+
+ // Rolling update config params. Present only if type = "RollingUpdate".
+ //---
+ // TODO: Update this to follow our convention for oneOf, whatever we decide it
+ // to be. Same as Deployment `strategy.rollingUpdate`.
+ // See https://github.com/kubernetes/kubernetes/issues/35345
+ // +optional
+ RollingUpdate *RollingUpdateDaemonSet `json:"rollingUpdate,omitempty"`
+}
+
+type DaemonSetUpdateStrategyType string
+
+const (
+ // Replace the old daemons by new ones using rolling update i.e replace them on each node one after the other.
+ RollingUpdateDaemonSetStrategyType DaemonSetUpdateStrategyType = "RollingUpdate"
+
+ // Replace the old daemons only when it's killed
+ OnDeleteDaemonSetStrategyType DaemonSetUpdateStrategyType = "OnDelete"
+)
+
+// Spec to control the desired behavior of daemon set rolling update.
+type RollingUpdateDaemonSet struct {
+ // The maximum number of DaemonSet pods that can be unavailable during the
+ // update. Value can be an absolute number (ex: 5) or a percentage of total
+ // number of DaemonSet pods at the start of the update (ex: 10%). Absolute
+ // number is calculated from percentage by rounding up.
+ // This cannot be 0 if MaxSurge is 0
+ // Default value is 1.
+ // Example: when this is set to 30%, at most 30% of the total number of nodes
+ // that should be running the daemon pod (i.e. status.desiredNumberScheduled)
+ // can have their pods stopped for an update at any given time. The update
+ // starts by stopping at most 30% of those DaemonSet pods and then brings
+ // up new DaemonSet pods in their place. Once the new pods are available,
+ // it then proceeds onto other DaemonSet pods, thus ensuring that at least
+ // 70% of original number of DaemonSet pods are available at all times during
+ // the update.
+ // +optional
+ MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"`
+
+ // The maximum number of nodes with an existing available DaemonSet pod that
+ // can have an updated DaemonSet pod during during an update.
+ // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
+ // This can not be 0 if MaxUnavailable is 0.
+ // Absolute number is calculated from percentage by rounding up to a minimum of 1.
+ // Default value is 0.
+ // Example: when this is set to 30%, at most 30% of the total number of nodes
+ // that should be running the daemon pod (i.e. status.desiredNumberScheduled)
+ // can have their a new pod created before the old pod is marked as deleted.
+ // The update starts by launching new pods on 30% of nodes. Once an updated
+ // pod is available (Ready for at least minReadySeconds) the old DaemonSet pod
+ // on that node is marked deleted. If the old pod becomes unavailable for any
+ // reason (Ready transitions to false, is evicted, or is drained) an updated
+ // pod is immediatedly created on that node without considering surge limits.
+ // Allowing surge implies the possibility that the resources consumed by the
+ // daemonset on any given node can double if the readiness check fails, and
+ // so resource intensive daemonsets should take into account that they may
+ // cause evictions during disruption.
+ // This is beta field and enabled/disabled by DaemonSetUpdateSurge feature gate.
+ // +optional
+ MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty"`
+}
+
+// DaemonSetSpec is the specification of a daemon set.
+type DaemonSetSpec struct {
+ // A label query over pods that are managed by the daemon set.
+ // Must match in order to be controlled.
+ // It must match the pod template's labels.
+ // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
+ Selector *metav1.LabelSelector `json:"selector"`
+
+ // An object that describes the pod that will be created.
+ // The DaemonSet will create exactly one copy of this pod on every node
+ // that matches the template's node selector (or on every node if no node
+ // selector is specified).
+ // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template
+ Template v1.PodTemplateSpec `json:"template"`
+
+ // An update strategy to replace existing DaemonSet pods with new pods.
+ // +optional
+ UpdateStrategy DaemonSetUpdateStrategy `json:"updateStrategy,omitempty"`
+
+ // The minimum number of seconds for which a newly created DaemonSet pod should
+ // be ready without any of its container crashing, for it to be considered
+ // available. Defaults to 0 (pod will be considered available as soon as it
+ // is ready).
+ // +optional
+ MinReadySeconds int32 `json:"minReadySeconds,omitempty"`
+
+ // The number of old history to retain to allow rollback.
+ // This is a pointer to distinguish between explicit zero and not specified.
+ // Defaults to 10.
+ // +optional
+ RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty"`
+}
+
+// DaemonSetStatus represents the current status of a daemon set.
+type DaemonSetStatus struct {
+ // The number of nodes that are running at least 1
+ // daemon pod and are supposed to run the daemon pod.
+ // More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
+ CurrentNumberScheduled int32 `json:"currentNumberScheduled"`
+
+ // The number of nodes that are running the daemon pod, but are
+ // not supposed to run the daemon pod.
+ // More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
+ NumberMisscheduled int32 `json:"numberMisscheduled"`
+
+ // The total number of nodes that should be running the daemon
+ // pod (including nodes correctly running the daemon pod).
+ // More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
+ DesiredNumberScheduled int32 `json:"desiredNumberScheduled"`
+
+ // The number of nodes that should be running the daemon pod and have one
+ // or more of the daemon pod running and ready.
+ NumberReady int32 `json:"numberReady"`
+
+ // The most recent generation observed by the daemon set controller.
+ // +optional
+ ObservedGeneration int64 `json:"observedGeneration,omitempty"`
+
+ // The total number of nodes that are running updated daemon pod
+ // +optional
+ UpdatedNumberScheduled int32 `json:"updatedNumberScheduled,omitempty"`
+
+ // The number of nodes that should be running the
+ // daemon pod and have one or more of the daemon pod running and
+ // available (ready for at least spec.minReadySeconds)
+ // +optional
+ NumberAvailable int32 `json:"numberAvailable,omitempty"`
+
+ // The number of nodes that should be running the
+ // daemon pod and have none of the daemon pod running and available
+ // (ready for at least spec.minReadySeconds)
+ // +optional
+ NumberUnavailable int32 `json:"numberUnavailable,omitempty"`
+
+ // Count of hash collisions for the DaemonSet. The DaemonSet controller
+ // uses this field as a collision avoidance mechanism when it needs to
+ // create the name for the newest ControllerRevision.
+ // +optional
+ CollisionCount *int32 `json:"collisionCount,omitempty"`
+
+ // Represents the latest available observations of a DaemonSet's current state.
+ // +optional
+ // +patchMergeKey=type
+ // +patchStrategy=merge
+ Conditions []DaemonSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
+}
+
+type DaemonSetConditionType string
+
+// TODO: Add valid condition types of a DaemonSet.
+
+// DaemonSetCondition describes the state of a DaemonSet at a certain point.
+type DaemonSetCondition struct {
+ // Type of DaemonSet condition.
+ Type DaemonSetConditionType `json:"type"`
+ // Status of the condition, one of True, False, Unknown.
+ Status v1.ConditionStatus `json:"status"`
+ // Last time the condition transitioned from one status to another.
+ // +optional
+ LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
+ // The reason for the condition's last transition.
+ // +optional
+ Reason string `json:"reason,omitempty"`
+ // A human readable message indicating details about the transition.
+ // +optional
+ Message string `json:"message,omitempty"`
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// DaemonSet represents the configuration of a daemon set.
+type DaemonSet struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // The desired behavior of this daemon set.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Spec DaemonSetSpec `json:"spec,omitempty"`
+
+ // The current status of this daemon set. This data may be
+ // out of date by some window of time.
+ // Populated by the system.
+ // Read-only.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Status DaemonSetStatus `json:"status,omitempty"`
+}
+
+const (
+ // DefaultDaemonSetUniqueLabelKey is the default label key that is added
+ // to existing DaemonSet pods to distinguish between old and new
+ // DaemonSet pods during DaemonSet template updates.
+ DefaultDaemonSetUniqueLabelKey = ControllerRevisionHashLabelKey
+)
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// DaemonSetList is a collection of daemon sets.
+type DaemonSetList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // A list of daemon sets.
+ Items []DaemonSet `json:"items"`
+}
+
+// +genclient
+// +genclient:method=GetScale,verb=get,subresource=scale,result=k8s.io/api/autoscaling/v1.Scale
+// +genclient:method=UpdateScale,verb=update,subresource=scale,input=k8s.io/api/autoscaling/v1.Scale,result=k8s.io/api/autoscaling/v1.Scale
+// +genclient:method=ApplyScale,verb=apply,subresource=scale,input=k8s.io/api/autoscaling/v1.Scale,result=k8s.io/api/autoscaling/v1.Scale
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ReplicaSet ensures that a specified number of pod replicas are running at any given time.
+type ReplicaSet struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // If the Labels of a ReplicaSet are empty, they are defaulted to
+ // be the same as the Pod(s) that the ReplicaSet manages.
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Spec defines the specification of the desired behavior of the ReplicaSet.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Spec ReplicaSetSpec `json:"spec,omitempty"`
+
+ // Status is the most recently observed status of the ReplicaSet.
+ // This data may be out of date by some window of time.
+ // Populated by the system.
+ // Read-only.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Status ReplicaSetStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ReplicaSetList is a collection of ReplicaSets.
+type ReplicaSetList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // List of ReplicaSets.
+ // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller
+ Items []ReplicaSet `json:"items"`
+}
+
+// ReplicaSetSpec is the specification of a ReplicaSet.
+type ReplicaSetSpec struct {
+ // Replicas is the number of desired replicas.
+ // This is a pointer to distinguish between explicit zero and unspecified.
+ // Defaults to 1.
+ // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/#what-is-a-replicationcontroller
+ // +optional
+ Replicas *int32 `json:"replicas,omitempty"`
+
+ // Minimum number of seconds for which a newly created pod should be ready
+ // without any of its container crashing, for it to be considered available.
+ // Defaults to 0 (pod will be considered available as soon as it is ready)
+ // +optional
+ MinReadySeconds int32 `json:"minReadySeconds,omitempty"`
+
+ // Selector is a label query over pods that should match the replica count.
+ // Label keys and values that must match in order to be controlled by this replica set.
+ // It must match the pod template's labels.
+ // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
+ Selector *metav1.LabelSelector `json:"selector"`
+
+ // Template is the object that describes the pod that will be created if
+ // insufficient replicas are detected.
+ // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template
+ // +optional
+ Template v1.PodTemplateSpec `json:"template,omitempty"`
+}
+
+// ReplicaSetStatus represents the current status of a ReplicaSet.
+type ReplicaSetStatus struct {
+ // Replicas is the most recently oberved number of replicas.
+ // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/#what-is-a-replicationcontroller
+ Replicas int32 `json:"replicas"`
+
+ // The number of pods that have labels matching the labels of the pod template of the replicaset.
+ // +optional
+ FullyLabeledReplicas int32 `json:"fullyLabeledReplicas,omitempty"`
+
+ // The number of ready replicas for this replica set.
+ // +optional
+ ReadyReplicas int32 `json:"readyReplicas,omitempty"`
+
+ // The number of available replicas (ready for at least minReadySeconds) for this replica set.
+ // +optional
+ AvailableReplicas int32 `json:"availableReplicas,omitempty"`
+
+ // ObservedGeneration reflects the generation of the most recently observed ReplicaSet.
+ // +optional
+ ObservedGeneration int64 `json:"observedGeneration,omitempty"`
+
+ // Represents the latest available observations of a replica set's current state.
+ // +optional
+ // +patchMergeKey=type
+ // +patchStrategy=merge
+ Conditions []ReplicaSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
+}
+
+type ReplicaSetConditionType string
+
+// These are valid conditions of a replica set.
+const (
+ // ReplicaSetReplicaFailure is added in a replica set when one of its pods fails to be created
+ // due to insufficient quota, limit ranges, pod security policy, node selectors, etc. or deleted
+ // due to kubelet being down or finalizers are failing.
+ ReplicaSetReplicaFailure ReplicaSetConditionType = "ReplicaFailure"
+)
+
+// ReplicaSetCondition describes the state of a replica set at a certain point.
+type ReplicaSetCondition struct {
+ // Type of replica set condition.
+ Type ReplicaSetConditionType `json:"type"`
+ // Status of the condition, one of True, False, Unknown.
+ Status v1.ConditionStatus `json:"status"`
+ // The last time the condition transitioned from one status to another.
+ // +optional
+ LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
+ // The reason for the condition's last transition.
+ // +optional
+ Reason string `json:"reason,omitempty"`
+ // A human readable message indicating details about the transition.
+ // +optional
+ Message string `json:"message,omitempty"`
+}
diff --git a/pkg/k8s.io/api/core/v1/annotation_key_constants.go b/pkg/k8s.io/api/core/v1/annotation_key_constants.go
new file mode 100644
index 000000000..7fde09126
--- /dev/null
+++ b/pkg/k8s.io/api/core/v1/annotation_key_constants.go
@@ -0,0 +1,151 @@
+/*
+Copyright 2017 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// This file should be consistent with pkg/api/annotation_key_constants.go.
+
+package v1
+
+const (
+ // ImagePolicyFailedOpenKey is added to pods created by failing open when the image policy
+ // webhook backend fails.
+ ImagePolicyFailedOpenKey string = "alpha.image-policy.k8s.io/failed-open"
+
+ // MirrorAnnotationKey represents the annotation key set by kubelets when creating mirror pods
+ MirrorPodAnnotationKey string = "kubernetes.io/config.mirror"
+
+ // TolerationsAnnotationKey represents the key of tolerations data (json serialized)
+ // in the Annotations of a Pod.
+ TolerationsAnnotationKey string = "scheduler.alpha.kubernetes.io/tolerations"
+
+ // TaintsAnnotationKey represents the key of taints data (json serialized)
+ // in the Annotations of a Node.
+ TaintsAnnotationKey string = "scheduler.alpha.kubernetes.io/taints"
+
+ // SeccompPodAnnotationKey represents the key of a seccomp profile applied
+ // to all containers of a pod.
+ // Deprecated: set a pod security context `seccompProfile` field.
+ SeccompPodAnnotationKey string = "seccomp.security.alpha.kubernetes.io/pod"
+
+ // SeccompContainerAnnotationKeyPrefix represents the key of a seccomp profile applied
+ // to one container of a pod.
+ // Deprecated: set a container security context `seccompProfile` field.
+ SeccompContainerAnnotationKeyPrefix string = "container.seccomp.security.alpha.kubernetes.io/"
+
+ // SeccompProfileRuntimeDefault represents the default seccomp profile used by container runtime.
+ // Deprecated: set a pod or container security context `seccompProfile` of type "RuntimeDefault" instead.
+ SeccompProfileRuntimeDefault string = "runtime/default"
+
+ // SeccompProfileNameUnconfined is the unconfined seccomp profile.
+ SeccompProfileNameUnconfined string = "unconfined"
+
+ // SeccompLocalhostProfileNamePrefix is the prefix for specifying profiles loaded from the node's disk.
+ SeccompLocalhostProfileNamePrefix = "localhost/"
+
+ // AppArmorBetaContainerAnnotationKeyPrefix is the prefix to an annotation key specifying a container's apparmor profile.
+ AppArmorBetaContainerAnnotationKeyPrefix = "container.apparmor.security.beta.kubernetes.io/"
+ // AppArmorBetaDefaultProfileAnnotatoinKey is the annotation key specifying the default AppArmor profile.
+ AppArmorBetaDefaultProfileAnnotationKey = "apparmor.security.beta.kubernetes.io/defaultProfileName"
+ // AppArmorBetaAllowedProfileAnnotationKey is the annotation key specifying the allowed AppArmor profiles.
+ AppArmorBetaAllowedProfilesAnnotationKey = "apparmor.security.beta.kubernetes.io/allowedProfileNames"
+
+ // AppArmorBetaProfileRuntimeDefault is the profile specifying the runtime default.
+ AppArmorBetaProfileRuntimeDefault = "runtime/default"
+
+ // AppArmorBetaProfileNamePrefix is the prefix for specifying profiles loaded on the node.
+ AppArmorBetaProfileNamePrefix = "localhost/"
+
+ // AppArmorBetaProfileNameUnconfined is the Unconfined AppArmor profile
+ AppArmorBetaProfileNameUnconfined = "unconfined"
+
+ // DeprecatedSeccompProfileDockerDefault represents the default seccomp profile used by docker.
+ // Deprecated: set a pod or container security context `seccompProfile` of type "RuntimeDefault" instead.
+ DeprecatedSeccompProfileDockerDefault string = "docker/default"
+
+ // PreferAvoidPodsAnnotationKey represents the key of preferAvoidPods data (json serialized)
+ // in the Annotations of a Node.
+ PreferAvoidPodsAnnotationKey string = "scheduler.alpha.kubernetes.io/preferAvoidPods"
+
+ // ObjectTTLAnnotations represents a suggestion for kubelet for how long it can cache
+ // an object (e.g. secret, config map) before fetching it again from apiserver.
+ // This annotation can be attached to node.
+ ObjectTTLAnnotationKey string = "node.alpha.kubernetes.io/ttl"
+
+ // annotation key prefix used to identify non-convertible json paths.
+ NonConvertibleAnnotationPrefix = "non-convertible.kubernetes.io"
+
+ kubectlPrefix = "kubectl.kubernetes.io/"
+
+ // LastAppliedConfigAnnotation is the annotation used to store the previous
+ // configuration of a resource for use in a three way diff by UpdateApplyAnnotation.
+ LastAppliedConfigAnnotation = kubectlPrefix + "last-applied-configuration"
+
+ // AnnotationLoadBalancerSourceRangesKey is the key of the annotation on a service to set allowed ingress ranges on their LoadBalancers
+ //
+ // It should be a comma-separated list of CIDRs, e.g. `0.0.0.0/0` to
+ // allow full access (the default) or `18.0.0.0/8,56.0.0.0/8` to allow
+ // access only from the CIDRs currently allocated to MIT & the USPS.
+ //
+ // Not all cloud providers support this annotation, though AWS & GCE do.
+ AnnotationLoadBalancerSourceRangesKey = "service.beta.kubernetes.io/load-balancer-source-ranges"
+
+ // EndpointsLastChangeTriggerTime is the annotation key, set for endpoints objects, that
+ // represents the timestamp (stored as RFC 3339 date-time string, e.g. '2018-10-22T19:32:52.1Z')
+ // of the last change, of some Pod or Service object, that triggered the endpoints object change.
+ // In other words, if a Pod / Service changed at time T0, that change was observed by endpoints
+ // controller at T1, and the Endpoints object was changed at T2, the
+ // EndpointsLastChangeTriggerTime would be set to T0.
+ //
+ // The "endpoints change trigger" here means any Pod or Service change that resulted in the
+ // Endpoints object change.
+ //
+ // Given the definition of the "endpoints change trigger", please note that this annotation will
+ // be set ONLY for endpoints object changes triggered by either Pod or Service change. If the
+ // Endpoints object changes due to other reasons, this annotation won't be set (or updated if it's
+ // already set).
+ //
+ // This annotation will be used to compute the in-cluster network programming latency SLI, see
+ // https://github.com/kubernetes/community/blob/master/sig-scalability/slos/network_programming_latency.md
+ EndpointsLastChangeTriggerTime = "endpoints.kubernetes.io/last-change-trigger-time"
+
+ // EndpointsOverCapacity will be set on an Endpoints resource when it
+ // exceeds the maximum capacity of 1000 addresses. Inititially the Endpoints
+ // controller will set this annotation with a value of "warning". In a
+ // future release, the controller may set this annotation with a value of
+ // "truncated" to indicate that any addresses exceeding the limit of 1000
+ // have been truncated from the Endpoints resource.
+ EndpointsOverCapacity = "endpoints.kubernetes.io/over-capacity"
+
+ // MigratedPluginsAnnotationKey is the annotation key, set for CSINode objects, that is a comma-separated
+ // list of in-tree plugins that will be serviced by the CSI backend on the Node represented by CSINode.
+ // This annotation is used by the Attach Detach Controller to determine whether to use the in-tree or
+ // CSI Backend for a volume plugin on a specific node.
+ MigratedPluginsAnnotationKey = "storage.alpha.kubernetes.io/migrated-plugins"
+
+ // PodDeletionCost can be used to set to an int32 that represent the cost of deleting
+ // a pod compared to other pods belonging to the same ReplicaSet. Pods with lower
+ // deletion cost are preferred to be deleted before pods with higher deletion cost.
+ // Note that this is honored on a best-effort basis, and so it does not offer guarantees on
+ // pod deletion order.
+ // The implicit deletion cost for pods that don't set the annotation is 0, negative values are permitted.
+ //
+ // This annotation is beta-level and is only honored when PodDeletionCost feature is enabled.
+ PodDeletionCost = "controller.kubernetes.io/pod-deletion-cost"
+
+ // AnnotationTopologyAwareHints can be used to enable or disable Topology
+ // Aware Hints for a Service. This may be set to "Auto" or "Disabled". Any
+ // other value is treated as "Disabled".
+ AnnotationTopologyAwareHints = "service.kubernetes.io/topology-aware-hints"
+)
diff --git a/pkg/k8s.io/api/core/v1/resource.go b/pkg/k8s.io/api/core/v1/resource.go
new file mode 100644
index 000000000..9270054b3
--- /dev/null
+++ b/pkg/k8s.io/api/core/v1/resource.go
@@ -0,0 +1,60 @@
+/*
+Copyright 2017 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1
+
+import (
+ "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/api/resource"
+)
+
+// Returns string version of ResourceName.
+func (rn ResourceName) String() string {
+ return string(rn)
+}
+
+// Cpu returns the Cpu limit if specified.
+// nolint:golint,stylecheck
+func (rl *ResourceList) Cpu() *resource.Quantity {
+ return rl.Name(ResourceCPU, resource.DecimalSI)
+}
+
+// Memory returns the Memory limit if specified.
+func (rl *ResourceList) Memory() *resource.Quantity {
+ return rl.Name(ResourceMemory, resource.BinarySI)
+}
+
+// Storage returns the Storage limit if specified.
+func (rl *ResourceList) Storage() *resource.Quantity {
+ return rl.Name(ResourceStorage, resource.BinarySI)
+}
+
+// Pods returns the list of pods
+func (rl *ResourceList) Pods() *resource.Quantity {
+ return rl.Name(ResourcePods, resource.DecimalSI)
+}
+
+// StorageEphemeral returns the list of ephemeral storage volumes, if any
+func (rl *ResourceList) StorageEphemeral() *resource.Quantity {
+ return rl.Name(ResourceEphemeralStorage, resource.BinarySI)
+}
+
+// Name returns the resource with name if specified, otherwise it returns a nil quantity with default format.
+func (rl *ResourceList) Name(name ResourceName, defaultFormat resource.Format) *resource.Quantity {
+ if val, ok := (*rl)[name]; ok {
+ return &val
+ }
+ return &resource.Quantity{Format: defaultFormat}
+}
diff --git a/pkg/k8s.io/api/core/v1/types.go b/pkg/k8s.io/api/core/v1/types.go
new file mode 100644
index 000000000..833814bc6
--- /dev/null
+++ b/pkg/k8s.io/api/core/v1/types.go
@@ -0,0 +1,4468 @@
+/*
+Copyright 2015 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1
+
+import (
+ "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/api/resource"
+ metav1 "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/apis/meta/v1"
+ "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/types"
+ "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/util/intstr"
+)
+
+// Volume represents a named volume in a pod that may be accessed by any container in the pod.
+type Volume struct {
+ // Volume's name.
+ // Must be a DNS_LABEL and unique within the pod.
+ // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
+ Name string `json:"name"`
+ // VolumeSource represents the location and type of the mounted volume.
+ // If not specified, the Volume is implied to be an EmptyDir.
+ // This implied behavior is deprecated and will be removed in a future version.
+ VolumeSource `json:",inline"`
+}
+
+// Represents the source of a volume to mount.
+// Only one of its members may be specified.
+type VolumeSource struct {
+ // 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
+ // ---
+ // TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not
+ // mount host directories as read/write.
+ // +optional
+ HostPath *HostPathVolumeSource `json:"hostPath,omitempty"`
+ // PersistentVolumeClaimVolumeSource represents a reference to a
+ // PersistentVolumeClaim in the same namespace.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims
+ // +optional
+ PersistentVolumeClaim *PersistentVolumeClaimVolumeSource `json:"persistentVolumeClaim,omitempty"`
+ // ConfigMap represents a configMap that should populate this volume
+ // +optional
+ ConfigMap *ConfigMapVolumeSource `json:"configMap,omitempty"`
+}
+
+// PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace.
+// This volume finds the bound PV and mounts that volume for the pod. A
+// PersistentVolumeClaimVolumeSource is, essentially, a wrapper around another
+// type of volume that is owned by someone else (the system).
+type PersistentVolumeClaimVolumeSource struct {
+ // ClaimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims
+ ClaimName string `json:"claimName"`
+ // Will force the ReadOnly setting in VolumeMounts.
+ // Default false.
+ // +optional
+ ReadOnly bool `json:"readOnly,omitempty"`
+}
+
+// PersistentVolumeSource is similar to VolumeSource but meant for the
+// administrator who creates PVs. Exactly one of its members must be set.
+type PersistentVolumeSource struct {
+ // HostPath represents a directory on the host.
+ // Provisioned by a developer or tester.
+ // This is useful for single-node development and testing only!
+ // On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster.
+ // More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath
+ // +optional
+ HostPath *HostPathVolumeSource `json:"hostPath,omitempty"`
+}
+
+// +genclient
+// +genclient:nonNamespaced
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PersistentVolume (PV) is a storage resource provisioned by an administrator.
+// It is analogous to a node.
+// More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes
+type PersistentVolume struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Spec defines a specification of a persistent volume owned by the cluster.
+ // Provisioned by an administrator.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistent-volumes
+ // +optional
+ Spec PersistentVolumeSpec `json:"spec,omitempty"`
+
+ // Status represents the current information/status for the persistent volume.
+ // Populated by the system.
+ // Read-only.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistent-volumes
+ // +optional
+ Status PersistentVolumeStatus `json:"status,omitempty"`
+}
+
+// PersistentVolumeSpec is the specification of a persistent volume.
+type PersistentVolumeSpec struct {
+ // A description of the persistent volume's resources and capacity.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity
+ // +optional
+ Capacity ResourceList `json:"capacity,omitempty"`
+ // The actual volume backing the persistent volume.
+ PersistentVolumeSource `json:",inline"`
+ // AccessModes contains all ways the volume can be mounted.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes
+ // +optional
+ AccessModes []PersistentVolumeAccessMode `json:"accessModes,omitempty"`
+ // ClaimRef is part of a bi-directional binding between PersistentVolume and PersistentVolumeClaim.
+ // Expected to be non-nil when bound.
+ // claim.VolumeName is the authoritative bind between PV and PVC.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#binding
+ // +optional
+ ClaimRef *ObjectReference `json:"claimRef,omitempty"`
+ // 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
+ // +optional
+ PersistentVolumeReclaimPolicy PersistentVolumeReclaimPolicy `json:"persistentVolumeReclaimPolicy,omitempty"`
+ // Name of StorageClass to which this persistent volume belongs. Empty value
+ // means that this volume does not belong to any StorageClass.
+ // +optional
+ StorageClassName string `json:"storageClassName,omitempty"`
+ // A list of mount options, e.g. ["ro", "soft"]. Not validated - mount will
+ // simply fail if one is invalid.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options
+ // +optional
+ MountOptions []string `json:"mountOptions,omitempty"`
+ // volumeMode defines if a volume is intended to be used with a formatted filesystem
+ // or to remain in raw block state. Value of Filesystem is implied when not included in spec.
+ // +optional
+ VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty"`
+ // NodeAffinity defines constraints that limit what nodes this volume can be accessed from.
+ // This field influences the scheduling of pods that use this volume.
+ // +optional
+ NodeAffinity *VolumeNodeAffinity `json:"nodeAffinity,omitempty"`
+}
+
+// VolumeNodeAffinity defines constraints that limit what nodes this volume can be accessed from.
+type VolumeNodeAffinity struct {
+ // Required specifies hard node constraints that must be met.
+ Required *NodeSelector `json:"required,omitempty"`
+}
+
+// PersistentVolumeReclaimPolicy describes a policy for end-of-life maintenance of persistent volumes.
+type PersistentVolumeReclaimPolicy string
+
+const (
+ // PersistentVolumeReclaimRecycle 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.
+ PersistentVolumeReclaimRecycle PersistentVolumeReclaimPolicy = "Recycle"
+ // PersistentVolumeReclaimDelete means the volume will be deleted from Kubernetes on release from its claim.
+ // The volume plugin must support Deletion.
+ PersistentVolumeReclaimDelete PersistentVolumeReclaimPolicy = "Delete"
+ // PersistentVolumeReclaimRetain means the volume will be left in its current phase (Released) for manual reclamation by the administrator.
+ // The default policy is Retain.
+ PersistentVolumeReclaimRetain PersistentVolumeReclaimPolicy = "Retain"
+)
+
+// PersistentVolumeMode describes how a volume is intended to be consumed, either Block or Filesystem.
+type PersistentVolumeMode string
+
+const (
+ // PersistentVolumeBlock means the volume will not be formatted with a filesystem and will remain a raw block device.
+ PersistentVolumeBlock PersistentVolumeMode = "Block"
+ // PersistentVolumeFilesystem means the volume will be or is formatted with a filesystem.
+ PersistentVolumeFilesystem PersistentVolumeMode = "Filesystem"
+)
+
+// PersistentVolumeStatus is the current status of a persistent volume.
+type PersistentVolumeStatus struct {
+ // Phase indicates if a volume is available, bound to a claim, or released by a claim.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#phase
+ // +optional
+ Phase PersistentVolumePhase `json:"phase,omitempty"`
+ // A human-readable message indicating details about why the volume is in this state.
+ // +optional
+ Message string `json:"message,omitempty"`
+ // Reason is a brief CamelCase string that describes any failure and is meant
+ // for machine parsing and tidy display in the CLI.
+ // +optional
+ Reason string `json:"reason,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PersistentVolumeList is a list of PersistentVolume items.
+type PersistentVolumeList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+ // List of persistent volumes.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes
+ Items []PersistentVolume `json:"items"`
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PersistentVolumeClaim is a user's request for and claim to a persistent volume
+type PersistentVolumeClaim struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Spec defines the desired characteristics of a volume requested by a pod author.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims
+ // +optional
+ Spec PersistentVolumeClaimSpec `json:"spec,omitempty"`
+
+ // Status represents the current information/status of a persistent volume claim.
+ // Read-only.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims
+ // +optional
+ Status PersistentVolumeClaimStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PersistentVolumeClaimList is a list of PersistentVolumeClaim items.
+type PersistentVolumeClaimList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+ // A list of persistent volume claims.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims
+ Items []PersistentVolumeClaim `json:"items"`
+}
+
+// PersistentVolumeClaimSpec describes the common attributes of storage devices
+// and allows a Source for provider-specific attributes
+type PersistentVolumeClaimSpec struct {
+ // AccessModes contains the desired access modes the volume should have.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1
+ // +optional
+ AccessModes []PersistentVolumeAccessMode `json:"accessModes,omitempty"`
+ // A label query over volumes to consider for binding.
+ // +optional
+ Selector *metav1.LabelSelector `json:"selector,omitempty"`
+ // Resources represents the minimum resources the volume should have.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
+ // +optional
+ Resources ResourceRequirements `json:"resources,omitempty"`
+ // VolumeName is the binding reference to the PersistentVolume backing this claim.
+ // +optional
+ VolumeName string `json:"volumeName,omitempty"`
+ // Name of the StorageClass required by the claim.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1
+ // +optional
+ StorageClassName *string `json:"storageClassName,omitempty"`
+ // volumeMode defines what type of volume is required by the claim.
+ // Value of Filesystem is implied when not included in claim spec.
+ // +optional
+ VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty"`
+ // This field can be used to specify either:
+ // * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot)
+ // * An existing PVC (PersistentVolumeClaim)
+ // If the provisioner or an external controller can support the specified data source,
+ // it will create a new volume based on the contents of the specified data source.
+ // If the AnyVolumeDataSource feature gate is enabled, this field will always have
+ // the same contents as the DataSourceRef field.
+ // +optional
+ DataSource *TypedLocalObjectReference `json:"dataSource,omitempty"`
+ // Specifies the object from which to populate the volume with data, if a non-empty
+ // volume is desired. This may be any local object from a non-empty API group (non
+ // core object) or a PersistentVolumeClaim object.
+ // When this field is specified, volume binding will only succeed if the type of
+ // the specified object matches some installed volume populator or dynamic
+ // provisioner.
+ // This field will replace the functionality of the DataSource field and as such
+ // if both fields are non-empty, they must have the same value. For backwards
+ // compatibility, both fields (DataSource and DataSourceRef) will be set to the same
+ // value automatically if one of them is empty and the other is non-empty.
+ // There are two important differences between DataSource and DataSourceRef:
+ // * While DataSource only allows two specific types of objects, DataSourceRef
+ // allows any non-core object, as well as PersistentVolumeClaim objects.
+ // * While DataSource ignores disallowed values (dropping them), DataSourceRef
+ // preserves all values, and generates an error if a disallowed value is
+ // specified.
+ // (Alpha) Using this field requires the AnyVolumeDataSource feature gate to be enabled.
+ // +optional
+ DataSourceRef *TypedLocalObjectReference `json:"dataSourceRef,omitempty"`
+}
+
+// PersistentVolumeClaimConditionType is a valid value of PersistentVolumeClaimCondition.Type
+type PersistentVolumeClaimConditionType string
+
+const (
+ // PersistentVolumeClaimResizing - a user trigger resize of pvc has been started
+ PersistentVolumeClaimResizing PersistentVolumeClaimConditionType = "Resizing"
+ // PersistentVolumeClaimFileSystemResizePending - controller resize is finished and a file system resize is pending on node
+ PersistentVolumeClaimFileSystemResizePending PersistentVolumeClaimConditionType = "FileSystemResizePending"
+)
+
+// PersistentVolumeClaimCondition contails details about state of pvc
+type PersistentVolumeClaimCondition struct {
+ Type PersistentVolumeClaimConditionType `json:"type"`
+ Status ConditionStatus `json:"status"`
+ // Last time we probed the condition.
+ // +optional
+ LastProbeTime metav1.Time `json:"lastProbeTime,omitempty"`
+ // Last time the condition transitioned from one status to another.
+ // +optional
+ LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
+ // Unique, this should be a short, machine understandable string that gives the reason
+ // for condition's last transition. If it reports "ResizeStarted" that means the underlying
+ // persistent volume is being resized.
+ // +optional
+ Reason string `json:"reason,omitempty"`
+ // Human-readable message indicating details about last transition.
+ // +optional
+ Message string `json:"message,omitempty"`
+}
+
+// PersistentVolumeClaimStatus is the current status of a persistent volume claim.
+type PersistentVolumeClaimStatus struct {
+ // Phase represents the current phase of PersistentVolumeClaim.
+ // +optional
+ Phase PersistentVolumeClaimPhase `json:"phase,omitempty"`
+ // AccessModes contains the actual access modes the volume backing the PVC has.
+ // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1
+ // +optional
+ AccessModes []PersistentVolumeAccessMode `json:"accessModes,omitempty"`
+ // Represents the actual resources of the underlying volume.
+ // +optional
+ Capacity ResourceList `json:"capacity,omitempty"`
+ // Current Condition of persistent volume claim. If underlying persistent volume is being
+ // resized then the Condition will be set to 'ResizeStarted'.
+ // +optional
+ // +patchMergeKey=type
+ // +patchStrategy=merge
+ Conditions []PersistentVolumeClaimCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
+}
+
+type PersistentVolumeAccessMode string
+
+const (
+ // can be mounted in read/write mode to exactly 1 host
+ ReadWriteOnce PersistentVolumeAccessMode = "ReadWriteOnce"
+ // can be mounted in read-only mode to many hosts
+ ReadOnlyMany PersistentVolumeAccessMode = "ReadOnlyMany"
+ // can be mounted in read/write mode to many hosts
+ ReadWriteMany PersistentVolumeAccessMode = "ReadWriteMany"
+ // can be mounted in read/write mode to exactly 1 pod
+ // cannot be used in combination with other access modes
+ ReadWriteOncePod PersistentVolumeAccessMode = "ReadWriteOncePod"
+)
+
+type PersistentVolumePhase string
+
+const (
+ // used for PersistentVolumes that are not available
+ VolumePending PersistentVolumePhase = "Pending"
+ // used for PersistentVolumes that are not yet bound
+ // Available volumes are held by the binder and matched to PersistentVolumeClaims
+ VolumeAvailable PersistentVolumePhase = "Available"
+ // used for PersistentVolumes that are bound
+ VolumeBound PersistentVolumePhase = "Bound"
+ // used for PersistentVolumes where the bound PersistentVolumeClaim was deleted
+ // released volumes must be recycled before becoming available again
+ // this phase is used by the persistent volume claim binder to signal to another process to reclaim the resource
+ VolumeReleased PersistentVolumePhase = "Released"
+ // used for PersistentVolumes that failed to be correctly recycled or deleted after being released from a claim
+ VolumeFailed PersistentVolumePhase = "Failed"
+)
+
+type PersistentVolumeClaimPhase string
+
+const (
+ // used for PersistentVolumeClaims that are not yet bound
+ ClaimPending PersistentVolumeClaimPhase = "Pending"
+ // used for PersistentVolumeClaims that are bound
+ ClaimBound PersistentVolumeClaimPhase = "Bound"
+ // used for PersistentVolumeClaims that lost their underlying
+ // PersistentVolume. The claim was bound to a PersistentVolume and this
+ // volume does not exist any longer and all data on it was lost.
+ ClaimLost PersistentVolumeClaimPhase = "Lost"
+)
+
+type HostPathType string
+
+const (
+ // For backwards compatible, leave it empty if unset
+ HostPathUnset HostPathType = ""
+ // If nothing exists at the given path, an empty directory will be created there
+ // as needed with file mode 0755, having the same group and ownership with Kubelet.
+ HostPathDirectoryOrCreate HostPathType = "DirectoryOrCreate"
+ // A directory must exist at the given path
+ HostPathDirectory HostPathType = "Directory"
+ // If nothing exists at the given path, an empty file will be created there
+ // as needed with file mode 0644, having the same group and ownership with Kubelet.
+ HostPathFileOrCreate HostPathType = "FileOrCreate"
+ // A file must exist at the given path
+ HostPathFile HostPathType = "File"
+ // A UNIX socket must exist at the given path
+ HostPathSocket HostPathType = "Socket"
+ // A character device must exist at the given path
+ HostPathCharDev HostPathType = "CharDevice"
+ // A block device must exist at the given path
+ HostPathBlockDev HostPathType = "BlockDevice"
+)
+
+// Represents a host path mapped into a pod.
+// Host path volumes do not support ownership management or SELinux relabeling.
+type HostPathVolumeSource struct {
+ // Path of the directory on the host.
+ // If the path is a symlink, it will follow the link to the real path.
+ // More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath
+ Path string `json:"path"`
+ // Type for HostPath Volume
+ // Defaults to ""
+ // More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath
+ // +optional
+ Type *HostPathType `json:"type,omitempty"`
+}
+
+// Represents an empty directory for a pod.
+// Empty directory volumes support ownership management and SELinux relabeling.
+type EmptyDirVolumeSource struct {
+ // What type of storage medium should back this directory.
+ // The default is "" which means to use the node's default medium.
+ // Must be an empty string (default) or Memory.
+ // More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir
+ // +optional
+ Medium StorageMedium `json:"medium,omitempty"`
+ // Total amount of local storage required for this EmptyDir volume.
+ // The size limit is also applicable for memory medium.
+ // The maximum usage on memory medium EmptyDir would be the minimum value between
+ // the SizeLimit specified here and the sum of memory limits of all containers in a pod.
+ // The default is nil which means that the limit is undefined.
+ // More info: http://kubernetes.io/docs/user-guide/volumes#emptydir
+ // +optional
+ SizeLimit *resource.Quantity `json:"sizeLimit,omitempty"`
+}
+
+// SecretReference represents a Secret Reference. It has enough information to retrieve secret
+// in any namespace
+// +structType=atomic
+type SecretReference struct {
+ // Name is unique within a namespace to reference a secret resource.
+ // +optional
+ Name string `json:"name,omitempty"`
+ // Namespace defines the space within which the secret name must be unique.
+ // +optional
+ Namespace string `json:"namespace,omitempty"`
+}
+
+// StorageMedium defines ways that storage can be allocated to a volume.
+type StorageMedium string
+
+const (
+ StorageMediumDefault StorageMedium = "" // use whatever the default is for the node, assume anything we don't explicitly handle is this
+ StorageMediumMemory StorageMedium = "Memory" // use memory (e.g. tmpfs on linux)
+ StorageMediumHugePages StorageMedium = "HugePages" // use hugepages
+ StorageMediumHugePagesPrefix StorageMedium = "HugePages-" // prefix for full medium notation HugePages-<size>
+)
+
+// Protocol defines network protocols supported for things like container ports.
+type Protocol string
+
+const (
+ // ProtocolTCP is the TCP protocol.
+ ProtocolTCP Protocol = "TCP"
+ // ProtocolUDP is the UDP protocol.
+ ProtocolUDP Protocol = "UDP"
+ // ProtocolSCTP is the SCTP protocol.
+ ProtocolSCTP Protocol = "SCTP"
+)
+
+// Adapts a Secret into a volume.
+//
+// The contents of the target Secret's Data field will be presented in a volume
+// as files using the keys in the Data field as the file names.
+// Secret volumes support ownership management and SELinux relabeling.
+type SecretVolumeSource struct {
+ // Name of the secret in the pod's namespace to use.
+ // More info: https://kubernetes.io/docs/concepts/storage/volumes#secret
+ // +optional
+ SecretName string `json:"secretName,omitempty"`
+ // If unspecified, each key-value pair in the Data field of the referenced
+ // Secret will be projected into the volume as a file whose name is the
+ // key and content is the value. If specified, the listed keys will be
+ // projected into the specified paths, and unlisted keys will not be
+ // present. If a key is specified which is not present in the Secret,
+ // the volume setup will error unless it is marked optional. Paths must be
+ // relative and may not contain the '..' path or start with '..'.
+ // +optional
+ Items []KeyToPath `json:"items,omitempty"`
+ // Optional: mode bits used to set permissions on created files by default.
+ // Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511.
+ // YAML accepts both octal and decimal values, JSON requires decimal values
+ // for mode bits. Defaults to 0644.
+ // Directories within the path are not affected by this setting.
+ // This might be in conflict with other options that affect the file
+ // mode, like fsGroup, and the result can be other mode bits set.
+ // +optional
+ DefaultMode *int32 `json:"defaultMode,omitempty"`
+ // Specify whether the Secret or its keys must be defined
+ // +optional
+ Optional *bool `json:"optional,omitempty"`
+}
+
+const (
+ SecretVolumeSourceDefaultMode int32 = 0644
+)
+
+// Adapts a secret into a projected volume.
+//
+// The contents of the target Secret's Data field will be presented in a
+// projected volume as files using the keys in the Data field as the file names.
+// Note that this is identical to a secret volume source without the default
+// mode.
+type SecretProjection struct {
+ LocalObjectReference `json:",inline"`
+ // If unspecified, each key-value pair in the Data field of the referenced
+ // Secret will be projected into the volume as a file whose name is the
+ // key and content is the value. If specified, the listed keys will be
+ // projected into the specified paths, and unlisted keys will not be
+ // present. If a key is specified which is not present in the Secret,
+ // the volume setup will error unless it is marked optional. Paths must be
+ // relative and may not contain the '..' path or start with '..'.
+ // +optional
+ Items []KeyToPath `json:"items,omitempty"`
+ // Specify whether the Secret or its key must be defined
+ // +optional
+ Optional *bool `json:"optional,omitempty"`
+}
+
+// Adapts a ConfigMap into a volume.
+//
+// The contents of the target ConfigMap's Data field will be presented in a
+// volume as files using the keys in the Data field as the file names, unless
+// the items element is populated with specific mappings of keys to paths.
+// ConfigMap volumes support ownership management and SELinux relabeling.
+type ConfigMapVolumeSource struct {
+ LocalObjectReference `json:",inline"`
+ // If unspecified, each key-value pair in the Data field of the referenced
+ // ConfigMap will be projected into the volume as a file whose name is the
+ // key and content is the value. If specified, the listed keys will be
+ // projected into the specified paths, and unlisted keys will not be
+ // present. If a key is specified which is not present in the ConfigMap,
+ // the volume setup will error unless it is marked optional. Paths must be
+ // relative and may not contain the '..' path or start with '..'.
+ // +optional
+ Items []KeyToPath `json:"items,omitempty"`
+ // Optional: mode bits used to set permissions on created files by default.
+ // Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511.
+ // YAML accepts both octal and decimal values, JSON requires decimal values for mode bits.
+ // Defaults to 0644.
+ // Directories within the path are not affected by this setting.
+ // This might be in conflict with other options that affect the file
+ // mode, like fsGroup, and the result can be other mode bits set.
+ // +optional
+ DefaultMode *int32 `json:"defaultMode,omitempty"`
+ // Specify whether the ConfigMap or its keys must be defined
+ // +optional
+ Optional *bool `json:"optional,omitempty"`
+}
+
+const (
+ ConfigMapVolumeSourceDefaultMode int32 = 0644
+)
+
+// Adapts a ConfigMap into a projected volume.
+//
+// The contents of the target ConfigMap's Data field will be presented in a
+// projected volume as files using the keys in the Data field as the file names,
+// unless the items element is populated with specific mappings of keys to paths.
+// Note that this is identical to a configmap volume source without the default
+// mode.
+type ConfigMapProjection struct {
+ LocalObjectReference `json:",inline"`
+ // If unspecified, each key-value pair in the Data field of the referenced
+ // ConfigMap will be projected into the volume as a file whose name is the
+ // key and content is the value. If specified, the listed keys will be
+ // projected into the specified paths, and unlisted keys will not be
+ // present. If a key is specified which is not present in the ConfigMap,
+ // the volume setup will error unless it is marked optional. Paths must be
+ // relative and may not contain the '..' path or start with '..'.
+ // +optional
+ Items []KeyToPath `json:"items,omitempty"`
+ // Specify whether the ConfigMap or its keys must be defined
+ // +optional
+ Optional *bool `json:"optional,omitempty"`
+}
+
+// ServiceAccountTokenProjection represents a projected service account token
+// volume. This projection can be used to insert a service account token into
+// the pods runtime filesystem for use against APIs (Kubernetes API Server or
+// otherwise).
+type ServiceAccountTokenProjection struct {
+ // Audience is the intended audience of the token. A recipient of a token
+ // must identify itself with an identifier specified in the audience of the
+ // token, and otherwise should reject the token. The audience defaults to the
+ // identifier of the apiserver.
+ //+optional
+ Audience string `json:"audience,omitempty"`
+ // ExpirationSeconds is the requested duration of validity of the service
+ // account token. As the token approaches expiration, the kubelet volume
+ // plugin will proactively rotate the service account token. The kubelet will
+ // start trying to rotate the token if the token is older than 80 percent of
+ // its time to live or if the token is older than 24 hours.Defaults to 1 hour
+ // and must be at least 10 minutes.
+ //+optional
+ ExpirationSeconds *int64 `json:"expirationSeconds,omitempty"`
+ // Path is the path relative to the mount point of the file to project the
+ // token into.
+ Path string `json:"path"`
+}
+
+// Represents a projected volume source
+type ProjectedVolumeSource struct {
+ // list of volume projections
+ // +optional
+ Sources []VolumeProjection `json:"sources"`
+ // Mode bits used to set permissions on created files by default.
+ // Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511.
+ // YAML accepts both octal and decimal values, JSON requires decimal values for mode bits.
+ // Directories within the path are not affected by this setting.
+ // This might be in conflict with other options that affect the file
+ // mode, like fsGroup, and the result can be other mode bits set.
+ // +optional
+ DefaultMode *int32 `json:"defaultMode,omitempty"`
+}
+
+// Projection that may be projected along with other supported volume types
+type VolumeProjection struct {
+ // all types below are the supported types for projection into the same volume
+
+ // information about the secret data to project
+ // +optional
+ Secret *SecretProjection `json:"secret,omitempty"`
+ // information about the downwardAPI data to project
+ // +optional
+ DownwardAPI *DownwardAPIProjection `json:"downwardAPI,omitempty"`
+ // information about the configMap data to project
+ // +optional
+ ConfigMap *ConfigMapProjection `json:"configMap,omitempty"`
+ // information about the serviceAccountToken data to project
+ // +optional
+ ServiceAccountToken *ServiceAccountTokenProjection `json:"serviceAccountToken,omitempty"`
+}
+
+const (
+ ProjectedVolumeSourceDefaultMode int32 = 0644
+)
+
+// Maps a string key to a path within a volume.
+type KeyToPath struct {
+ // The key to project.
+ Key string `json:"key"`
+
+ // The relative path of the file to map the key to.
+ // May not be an absolute path.
+ // May not contain the path element '..'.
+ // May not start with the string '..'.
+ Path string `json:"path"`
+ // Optional: mode bits used to set permissions on this file.
+ // Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511.
+ // YAML accepts both octal and decimal values, JSON requires decimal values for mode bits.
+ // If not specified, the volume defaultMode will be used.
+ // This might be in conflict with other options that affect the file
+ // mode, like fsGroup, and the result can be other mode bits set.
+ // +optional
+ Mode *int32 `json:"mode,omitempty"`
+}
+
+// PersistentVolumeClaimTemplate is used to produce
+// PersistentVolumeClaim objects as part of an EphemeralVolumeSource.
+type PersistentVolumeClaimTemplate struct {
+ // May contain labels and annotations that will be copied into the PVC
+ // when creating it. No other fields are allowed and will be rejected during
+ // validation.
+ //
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // The specification for the PersistentVolumeClaim. The entire content is
+ // copied unchanged into the PVC that gets created from this
+ // template. The same fields as in a PersistentVolumeClaim
+ // are also valid here.
+ Spec PersistentVolumeClaimSpec `json:"spec"`
+}
+
+// ContainerPort represents a network port in a single container.
+type ContainerPort struct {
+ // If specified, this must be an IANA_SVC_NAME and unique within the pod. Each
+ // named port in a pod must have a unique name. Name for the port that can be
+ // referred to by services.
+ // +optional
+ Name string `json:"name,omitempty"`
+ // Number of port to expose on the host.
+ // If specified, this must be a valid port number, 0 < x < 65536.
+ // If HostNetwork is specified, this must match ContainerPort.
+ // Most containers do not need this.
+ // +optional
+ HostPort int32 `json:"hostPort,omitempty"`
+ // Number of port to expose on the pod's IP address.
+ // This must be a valid port number, 0 < x < 65536.
+ ContainerPort int32 `json:"containerPort"`
+ // Protocol for port. Must be UDP, TCP, or SCTP.
+ // Defaults to "TCP".
+ // +optional
+ // +default="TCP"
+ Protocol Protocol `json:"protocol,omitempty"`
+ // What host IP to bind the external port to.
+ // +optional
+ HostIP string `json:"hostIP,omitempty"`
+}
+
+// VolumeMount describes a mounting of a Volume within a container.
+type VolumeMount struct {
+ // This must match the Name of a Volume.
+ Name string `json:"name"`
+ // Mounted read-only if true, read-write otherwise (false or unspecified).
+ // Defaults to false.
+ // +optional
+ ReadOnly bool `json:"readOnly,omitempty"`
+ // Path within the container at which the volume should be mounted. Must
+ // not contain ':'.
+ MountPath string `json:"mountPath"`
+ // Path within the volume from which the container's volume should be mounted.
+ // Defaults to "" (volume's root).
+ // +optional
+ SubPath string `json:"subPath,omitempty"`
+ // mountPropagation determines how mounts are propagated from the host
+ // to container and the other way around.
+ // When not set, MountPropagationNone is used.
+ // This field is beta in 1.10.
+ // +optional
+ MountPropagation *MountPropagationMode `json:"mountPropagation,omitempty"`
+ // Expanded path within the volume from which the container's volume should be mounted.
+ // Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment.
+ // Defaults to "" (volume's root).
+ // SubPathExpr and SubPath are mutually exclusive.
+ // +optional
+ SubPathExpr string `json:"subPathExpr,omitempty"`
+}
+
+// MountPropagationMode describes mount propagation.
+type MountPropagationMode string
+
+const (
+ // MountPropagationNone means that the volume in a container will
+ // not receive new mounts from the host or other containers, and filesystems
+ // mounted inside the container won't be propagated to the host or other
+ // containers.
+ // Note that this mode corresponds to "private" in Linux terminology.
+ MountPropagationNone MountPropagationMode = "None"
+ // MountPropagationHostToContainer means that the volume in a container will
+ // receive new mounts from the host or other containers, but filesystems
+ // mounted inside the container won't be propagated to the host or other
+ // containers.
+ // Note that this mode is recursively applied to all mounts in the volume
+ // ("rslave" in Linux terminology).
+ MountPropagationHostToContainer MountPropagationMode = "HostToContainer"
+ // MountPropagationBidirectional means that the volume in a container will
+ // receive new mounts from the host or other containers, and its own mounts
+ // will be propagated from the container to the host or other containers.
+ // Note that this mode is recursively applied to all mounts in the volume
+ // ("rshared" in Linux terminology).
+ MountPropagationBidirectional MountPropagationMode = "Bidirectional"
+)
+
+// volumeDevice describes a mapping of a raw block device within a container.
+type VolumeDevice struct {
+ // name must match the name of a persistentVolumeClaim in the pod
+ Name string `json:"name"`
+ // devicePath is the path inside of the container that the device will be mapped to.
+ DevicePath string `json:"devicePath"`
+}
+
+// EnvVar represents an environment variable present in a Container.
+type EnvVar struct {
+ // Name of the environment variable. Must be a C_IDENTIFIER.
+ Name string `json:"name"`
+
+ // Optional: no more than one of the following may be specified.
+
+ // Variable references $(VAR_NAME) are expanded
+ // using the previously defined environment variables in the container and
+ // any service environment variables. If a variable cannot be resolved,
+ // the reference in the input string will be unchanged. Double $$ are reduced
+ // to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e.
+ // "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)".
+ // Escaped references will never be expanded, regardless of whether the variable
+ // exists or not.
+ // Defaults to "".
+ // +optional
+ Value string `json:"value,omitempty"`
+ // Source for the environment variable's value. Cannot be used if value is not empty.
+ // +optional
+ ValueFrom *EnvVarSource `json:"valueFrom,omitempty"`
+}
+
+// EnvVarSource represents a source for the value of an EnvVar.
+type EnvVarSource struct {
+ // Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['<KEY>']`, `metadata.annotations['<KEY>']`,
+ // spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.
+ // +optional
+ FieldRef *ObjectFieldSelector `json:"fieldRef,omitempty"`
+ // Selects a resource of the container: only resources limits and requests
+ // (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.
+ // +optional
+ ResourceFieldRef *ResourceFieldSelector `json:"resourceFieldRef,omitempty"`
+ // Selects a key of a ConfigMap.
+ // +optional
+ ConfigMapKeyRef *ConfigMapKeySelector `json:"configMapKeyRef,omitempty"`
+ // Selects a key of a secret in the pod's namespace
+ // +optional
+ SecretKeyRef *SecretKeySelector `json:"secretKeyRef,omitempty"`
+}
+
+// ObjectFieldSelector selects an APIVersioned field of an object.
+// +structType=atomic
+type ObjectFieldSelector struct {
+ // Version of the schema the FieldPath is written in terms of, defaults to "v1".
+ // +optional
+ APIVersion string `json:"apiVersion,omitempty"`
+ // Path of the field to select in the specified API version.
+ FieldPath string `json:"fieldPath"`
+}
+
+// ResourceFieldSelector represents container resources (cpu, memory) and their output format
+// +structType=atomic
+type ResourceFieldSelector struct {
+ // Container name: required for volumes, optional for env vars
+ // +optional
+ ContainerName string `json:"containerName,omitempty"`
+ // Required: resource to select
+ Resource string `json:"resource"`
+ // Specifies the output format of the exposed resources, defaults to "1"
+ // +optional
+ Divisor resource.Quantity `json:"divisor,omitempty"`
+}
+
+// Selects a key from a ConfigMap.
+// +structType=atomic
+type ConfigMapKeySelector struct {
+ // The ConfigMap to select from.
+ LocalObjectReference `json:",inline"`
+ // The key to select.
+ Key string `json:"key"`
+ // Specify whether the ConfigMap or its key must be defined
+ // +optional
+ Optional *bool `json:"optional,omitempty"`
+}
+
+// SecretKeySelector selects a key of a Secret.
+// +structType=atomic
+type SecretKeySelector struct {
+ // The name of the secret in the pod's namespace to select from.
+ LocalObjectReference `json:",inline"`
+ // The key of the secret to select from. Must be a valid secret key.
+ Key string `json:"key"`
+ // Specify whether the Secret or its key must be defined
+ // +optional
+ Optional *bool `json:"optional,omitempty"`
+}
+
+// EnvFromSource represents the source of a set of ConfigMaps
+type EnvFromSource struct {
+ // An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.
+ // +optional
+ Prefix string `json:"prefix,omitempty"`
+ // The ConfigMap to select from
+ // +optional
+ ConfigMapRef *ConfigMapEnvSource `json:"configMapRef,omitempty"`
+ // The Secret to select from
+ // +optional
+ SecretRef *SecretEnvSource `json:"secretRef,omitempty"`
+}
+
+// ConfigMapEnvSource selects a ConfigMap to populate the environment
+// variables with.
+//
+// The contents of the target ConfigMap's Data field will represent the
+// key-value pairs as environment variables.
+type ConfigMapEnvSource struct {
+ // The ConfigMap to select from.
+ LocalObjectReference `json:",inline"`
+ // Specify whether the ConfigMap must be defined
+ // +optional
+ Optional *bool `json:"optional,omitempty"`
+}
+
+// SecretEnvSource selects a Secret to populate the environment
+// variables with.
+//
+// The contents of the target Secret's Data field will represent the
+// key-value pairs as environment variables.
+type SecretEnvSource struct {
+ // The Secret to select from.
+ LocalObjectReference `json:",inline"`
+ // Specify whether the Secret must be defined
+ // +optional
+ Optional *bool `json:"optional,omitempty"`
+}
+
+// HTTPHeader describes a custom header to be used in HTTP probes
+type HTTPHeader struct {
+ // The header field name
+ Name string `json:"name"`
+ // The header field value
+ Value string `json:"value"`
+}
+
+// HTTPGetAction describes an action based on HTTP Get requests.
+type HTTPGetAction struct {
+ // Path to access on the HTTP server.
+ // +optional
+ Path string `json:"path,omitempty"`
+ // Name or number of the port to access on the container.
+ // Number must be in the range 1 to 65535.
+ // Name must be an IANA_SVC_NAME.
+ Port intstr.IntOrString `json:"port"`
+ // Host name to connect to, defaults to the pod IP. You probably want to set
+ // "Host" in httpHeaders instead.
+ // +optional
+ Host string `json:"host,omitempty"`
+ // Scheme to use for connecting to the host.
+ // Defaults to HTTP.
+ // +optional
+ Scheme URIScheme `json:"scheme,omitempty"`
+ // Custom headers to set in the request. HTTP allows repeated headers.
+ // +optional
+ HTTPHeaders []HTTPHeader `json:"httpHeaders,omitempty"`
+}
+
+// URIScheme identifies the scheme used for connection to a host for Get actions
+type URIScheme string
+
+const (
+ // URISchemeHTTP means that the scheme used will be http://
+ URISchemeHTTP URIScheme = "HTTP"
+ // URISchemeHTTPS means that the scheme used will be https://
+ URISchemeHTTPS URIScheme = "HTTPS"
+)
+
+// TCPSocketAction describes an action based on opening a socket
+type TCPSocketAction struct {
+ // Number or name of the port to access on the container.
+ // Number must be in the range 1 to 65535.
+ // Name must be an IANA_SVC_NAME.
+ Port intstr.IntOrString `json:"port"`
+ // Optional: Host name to connect to, defaults to the pod IP.
+ // +optional
+ Host string `json:"host,omitempty"`
+}
+
+// ExecAction describes a "run in container" action.
+type ExecAction struct {
+ // Command is the command line to execute inside the container, the working directory for the
+ // command is root ('/') in the container's filesystem. The command is simply exec'd, it is
+ // not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use
+ // a shell, you need to explicitly call out to that shell.
+ // Exit status of 0 is treated as live/healthy and non-zero is unhealthy.
+ // +optional
+ Command []string `json:"command,omitempty"`
+}
+
+// Probe describes a health check to be performed against a container to determine whether it is
+// alive or ready to receive traffic.
+type Probe struct {
+ // The action taken to determine the health of a container
+ Handler `json:",inline"`
+ // Number of seconds after the container has started before liveness probes are initiated.
+ // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
+ // +optional
+ InitialDelaySeconds int32 `json:"initialDelaySeconds,omitempty"`
+ // Number of seconds after which the probe times out.
+ // Defaults to 1 second. Minimum value is 1.
+ // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
+ // +optional
+ TimeoutSeconds int32 `json:"timeoutSeconds,omitempty"`
+ // How often (in seconds) to perform the probe.
+ // Default to 10 seconds. Minimum value is 1.
+ // +optional
+ PeriodSeconds int32 `json:"periodSeconds,omitempty"`
+ // Minimum consecutive successes for the probe to be considered successful after having failed.
+ // Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1.
+ // +optional
+ SuccessThreshold int32 `json:"successThreshold,omitempty"`
+ // Minimum consecutive failures for the probe to be considered failed after having succeeded.
+ // Defaults to 3. Minimum value is 1.
+ // +optional
+ FailureThreshold int32 `json:"failureThreshold,omitempty"`
+ // Optional duration in seconds the pod needs to terminate gracefully upon probe failure.
+ // The grace period is the duration in seconds after the processes running in the pod are sent
+ // a termination signal and the time when the processes are forcibly halted with a kill signal.
+ // Set this value longer than the expected cleanup time for your process.
+ // If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this
+ // value overrides the value provided by the pod spec.
+ // Value must be non-negative integer. The value zero indicates stop immediately via
+ // the kill signal (no opportunity to shut down).
+ // This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate.
+ // Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset.
+ // +optional
+ TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"`
+}
+
+// PullPolicy describes a policy for if/when to pull a container image
+type PullPolicy string
+
+const (
+ // PullAlways means that kubelet always attempts to pull the latest image. Container will fail If the pull fails.
+ PullAlways PullPolicy = "Always"
+ // PullNever means that kubelet never pulls an image, but only uses a local image. Container will fail if the image isn't present
+ PullNever PullPolicy = "Never"
+ // PullIfNotPresent means that kubelet pulls if the image isn't present on disk. Container will fail if the image isn't present and the pull fails.
+ PullIfNotPresent PullPolicy = "IfNotPresent"
+)
+
+// PreemptionPolicy describes a policy for if/when to preempt a pod.
+type PreemptionPolicy string
+
+const (
+ // PreemptLowerPriority means that pod can preempt other pods with lower priority.
+ PreemptLowerPriority PreemptionPolicy = "PreemptLowerPriority"
+ // PreemptNever means that pod never preempts other pods with lower priority.
+ PreemptNever PreemptionPolicy = "Never"
+)
+
+// TerminationMessagePolicy describes how termination messages are retrieved from a container.
+type TerminationMessagePolicy string
+
+const (
+ // TerminationMessageReadFile is the default behavior and will set the container status message to
+ // the contents of the container's terminationMessagePath when the container exits.
+ TerminationMessageReadFile TerminationMessagePolicy = "File"
+ // TerminationMessageFallbackToLogsOnError will read the most recent contents of the container logs
+ // for the container status message when the container exits with an error and the
+ // terminationMessagePath has no contents.
+ TerminationMessageFallbackToLogsOnError TerminationMessagePolicy = "FallbackToLogsOnError"
+)
+
+// Capability represent POSIX capabilities type
+type Capability string
+
+// Adds and removes POSIX capabilities from running containers.
+type Capabilities struct {
+ // Added capabilities
+ // +optional
+ Add []Capability `json:"add,omitempty"`
+ // Removed capabilities
+ // +optional
+ Drop []Capability `json:"drop,omitempty"`
+}
+
+// ResourceRequirements describes the compute resource requirements.
+type ResourceRequirements struct {
+ // Limits describes the maximum amount of compute resources allowed.
+ // More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
+ // +optional
+ Limits ResourceList `json:"limits,omitempty"`
+ // Requests describes the minimum amount of compute resources required.
+ // If Requests is omitted for a container, it defaults to Limits if that is explicitly specified,
+ // otherwise to an implementation-defined value.
+ // More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
+ // +optional
+ Requests ResourceList `json:"requests,omitempty"`
+}
+
+const (
+ // TerminationMessagePathDefault means the default path to capture the application termination message running in a container
+ TerminationMessagePathDefault string = "/dev/termination-log"
+)
+
+// A single application container that you want to run within a pod.
+type Container struct {
+ // Name of the container specified as a DNS_LABEL.
+ // Each container in a pod must have a unique name (DNS_LABEL).
+ // Cannot be updated.
+ Name string `json:"name"`
+ // Docker image name.
+ // More info: https://kubernetes.io/docs/concepts/containers/images
+ // This field is optional to allow higher level config management to default or override
+ // container images in workload controllers like Deployments and StatefulSets.
+ // +optional
+ Image string `json:"image,omitempty"`
+ // Entrypoint array. Not executed within a shell.
+ // The docker image's ENTRYPOINT is used if this is not provided.
+ // Variable references $(VAR_NAME) are expanded using the container's environment. If a variable
+ // cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced
+ // to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will
+ // produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless
+ // of whether the variable exists or not. Cannot be updated.
+ // More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
+ // +optional
+ Command []string `json:"command,omitempty"`
+ // Arguments to the entrypoint.
+ // The docker image's CMD is used if this is not provided.
+ // Variable references $(VAR_NAME) are expanded using the container's environment. If a variable
+ // cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced
+ // to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will
+ // produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless
+ // of whether the variable exists or not. Cannot be updated.
+ // More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
+ // +optional
+ Args []string `json:"args,omitempty"`
+ // Container's working directory.
+ // If not specified, the container runtime's default will be used, which
+ // might be configured in the container image.
+ // Cannot be updated.
+ // +optional
+ WorkingDir string `json:"workingDir,omitempty"`
+ // List of ports to expose from the container. Exposing a port here gives
+ // the system additional information about the network connections a
+ // container uses, but is primarily informational. Not specifying a port here
+ // DOES NOT prevent that port from being exposed. Any port which is
+ // listening on the default "0.0.0.0" address inside a container will be
+ // accessible from the network.
+ // Cannot be updated.
+ // +optional
+ // +patchMergeKey=containerPort
+ // +patchStrategy=merge
+ // +listType=map
+ // +listMapKey=containerPort
+ // +listMapKey=protocol
+ Ports []ContainerPort `json:"ports,omitempty" patchStrategy:"merge" patchMergeKey:"containerPort"`
+ // List of sources to populate environment variables in the container.
+ // The keys defined within a source must be a C_IDENTIFIER. All invalid keys
+ // will be reported as an event when the container is starting. When a key exists in multiple
+ // sources, the value associated with the last source will take precedence.
+ // Values defined by an Env with a duplicate key will take precedence.
+ // Cannot be updated.
+ // +optional
+ EnvFrom []EnvFromSource `json:"envFrom,omitempty"`
+ // List of environment variables to set in the container.
+ // Cannot be updated.
+ // +optional
+ // +patchMergeKey=name
+ // +patchStrategy=merge
+ Env []EnvVar `json:"env,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
+ // Compute Resources required by this container.
+ // Cannot be updated.
+ // More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
+ // +optional
+ Resources ResourceRequirements `json:"resources,omitempty"`
+ // Pod volumes to mount into the container's filesystem.
+ // Cannot be updated.
+ // +optional
+ // +patchMergeKey=mountPath
+ // +patchStrategy=merge
+ VolumeMounts []VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath"`
+ // volumeDevices is the list of block devices to be used by the container.
+ // +patchMergeKey=devicePath
+ // +patchStrategy=merge
+ // +optional
+ VolumeDevices []VolumeDevice `json:"volumeDevices,omitempty" patchStrategy:"merge" patchMergeKey:"devicePath"`
+ // Periodic probe of container liveness.
+ // Container will be restarted if the probe fails.
+ // Cannot be updated.
+ // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
+ // +optional
+ LivenessProbe *Probe `json:"livenessProbe,omitempty"`
+ // Periodic probe of container service readiness.
+ // Container will be removed from service endpoints if the probe fails.
+ // Cannot be updated.
+ // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
+ // +optional
+ ReadinessProbe *Probe `json:"readinessProbe,omitempty"`
+ // StartupProbe indicates that the Pod has successfully initialized.
+ // If specified, no other probes are executed until this completes successfully.
+ // If this probe fails, the Pod will be restarted, just as if the livenessProbe failed.
+ // This can be used to provide different probe parameters at the beginning of a Pod's lifecycle,
+ // when it might take a long time to load data or warm a cache, than during steady-state operation.
+ // This cannot be updated.
+ // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
+ // +optional
+ StartupProbe *Probe `json:"startupProbe,omitempty"`
+ // Actions that the management system should take in response to container lifecycle events.
+ // Cannot be updated.
+ // +optional
+ Lifecycle *Lifecycle `json:"lifecycle,omitempty"`
+ // Optional: Path at which the file to which the container's termination message
+ // will be written is mounted into the container's filesystem.
+ // Message written is intended to be brief final status, such as an assertion failure message.
+ // Will be truncated by the node if greater than 4096 bytes. The total message length across
+ // all containers will be limited to 12kb.
+ // Defaults to /dev/termination-log.
+ // Cannot be updated.
+ // +optional
+ TerminationMessagePath string `json:"terminationMessagePath,omitempty"`
+ // Indicate how the termination message should be populated. File will use the contents of
+ // terminationMessagePath to populate the container status message on both success and failure.
+ // FallbackToLogsOnError will use the last chunk of container log output if the termination
+ // message file is empty and the container exited with an error.
+ // The log output is limited to 2048 bytes or 80 lines, whichever is smaller.
+ // Defaults to File.
+ // Cannot be updated.
+ // +optional
+ TerminationMessagePolicy TerminationMessagePolicy `json:"terminationMessagePolicy,omitempty"`
+ // Image pull policy.
+ // One of Always, Never, IfNotPresent.
+ // Defaults to Always if :latest tag is specified, or IfNotPresent otherwise.
+ // Cannot be updated.
+ // More info: https://kubernetes.io/docs/concepts/containers/images#updating-images
+ // +optional
+ ImagePullPolicy PullPolicy `json:"imagePullPolicy,omitempty"`
+ // SecurityContext defines the security options the container should be run with.
+ // If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext.
+ // More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
+ // +optional
+ SecurityContext *SecurityContext `json:"securityContext,omitempty"`
+
+ // Variables for interactive containers, these have very specialized use-cases (e.g. debugging)
+ // and shouldn't be used for general purpose containers.
+
+ // Whether this container should allocate a buffer for stdin in the container runtime. If this
+ // is not set, reads from stdin in the container will always result in EOF.
+ // Default is false.
+ // +optional
+ Stdin bool `json:"stdin,omitempty"`
+ // Whether the container runtime should close the stdin channel after it has been opened by
+ // a single attach. When stdin is true the stdin stream will remain open across multiple attach
+ // sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the
+ // first client attaches to stdin, and then remains open and accepts data until the client disconnects,
+ // at which time stdin is closed and remains closed until the container is restarted. If this
+ // flag is false, a container processes that reads from stdin will never receive an EOF.
+ // Default is false
+ // +optional
+ StdinOnce bool `json:"stdinOnce,omitempty"`
+ // Whether this container should allocate a TTY for itself, also requires 'stdin' to be true.
+ // Default is false.
+ // +optional
+ TTY bool `json:"tty,omitempty"`
+}
+
+// Handler defines a specific action that should be taken
+// TODO: pass structured data to these actions, and document that data here.
+type Handler struct {
+ // One and only one of the following should be specified.
+ // Exec specifies the action to take.
+ // +optional
+ Exec *ExecAction `json:"exec,omitempty"`
+ // HTTPGet specifies the http request to perform.
+ // +optional
+ HTTPGet *HTTPGetAction `json:"httpGet,omitempty"`
+ // TCPSocket specifies an action involving a TCP port.
+ // TCP hooks not yet supported
+ // TODO: implement a realistic TCP lifecycle hook
+ // +optional
+ TCPSocket *TCPSocketAction `json:"tcpSocket,omitempty"`
+}
+
+// Lifecycle describes actions that the management system should take in response to container lifecycle
+// events. For the PostStart and PreStop lifecycle handlers, management of the container blocks
+// until the action is complete, unless the container process fails, in which case the handler is aborted.
+type Lifecycle struct {
+ // PostStart is called immediately after a container is created. If the handler fails,
+ // the container is terminated and restarted according to its restart policy.
+ // Other management of the container blocks until the hook completes.
+ // More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks
+ // +optional
+ PostStart *Handler `json:"postStart,omitempty"`
+ // PreStop is called immediately before a container is terminated due to an
+ // API request or management event such as liveness/startup probe failure,
+ // preemption, resource contention, etc. The handler is not called if the
+ // container crashes or exits. The reason for termination is passed to the
+ // handler. The Pod's termination grace period countdown begins before the
+ // PreStop hooked is executed. Regardless of the outcome of the handler, the
+ // container will eventually terminate within the Pod's termination grace
+ // period. Other management of the container blocks until the hook completes
+ // or until the termination grace period is reached.
+ // More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks
+ // +optional
+ PreStop *Handler `json:"preStop,omitempty"`
+}
+
+type ConditionStatus string
+
+// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
+// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
+// can't decide if a resource is in the condition or not. In the future, we could add other
+// intermediate conditions, e.g. ConditionDegraded.
+const (
+ ConditionTrue ConditionStatus = "True"
+ ConditionFalse ConditionStatus = "False"
+ ConditionUnknown ConditionStatus = "Unknown"
+)
+
+// ContainerStateWaiting is a waiting state of a container.
+type ContainerStateWaiting struct {
+ // (brief) reason the container is not yet running.
+ // +optional
+ Reason string `json:"reason,omitempty"`
+ // Message regarding why the container is not yet running.
+ // +optional
+ Message string `json:"message,omitempty"`
+}
+
+// ContainerStateRunning is a running state of a container.
+type ContainerStateRunning struct {
+ // Time at which the container was last (re-)started
+ // +optional
+ StartedAt metav1.Time `json:"startedAt,omitempty"`
+}
+
+// ContainerStateTerminated is a terminated state of a container.
+type ContainerStateTerminated struct {
+ // Exit status from the last termination of the container
+ ExitCode int32 `json:"exitCode"`
+ // Signal from the last termination of the container
+ // +optional
+ Signal int32 `json:"signal,omitempty"`
+ // (brief) reason from the last termination of the container
+ // +optional
+ Reason string `json:"reason,omitempty"`
+ // Message regarding the last termination of the container
+ // +optional
+ Message string `json:"message,omitempty"`
+ // Time at which previous execution of the container started
+ // +optional
+ StartedAt metav1.Time `json:"startedAt,omitempty"`
+ // Time at which the container last terminated
+ // +optional
+ FinishedAt metav1.Time `json:"finishedAt,omitempty"`
+ // Container's ID in the format 'docker://<container_id>'
+ // +optional
+ ContainerID string `json:"containerID,omitempty"`
+}
+
+// ContainerState holds a possible state of container.
+// Only one of its members may be specified.
+// If none of them is specified, the default one is ContainerStateWaiting.
+type ContainerState struct {
+ // Details about a waiting container
+ // +optional
+ Waiting *ContainerStateWaiting `json:"waiting,omitempty"`
+ // Details about a running container
+ // +optional
+ Running *ContainerStateRunning `json:"running,omitempty"`
+ // Details about a terminated container
+ // +optional
+ Terminated *ContainerStateTerminated `json:"terminated,omitempty"`
+}
+
+// ContainerStatus contains details for the current status of this container.
+type ContainerStatus struct {
+ // This must be a DNS_LABEL. Each container in a pod must have a unique name.
+ // Cannot be updated.
+ Name string `json:"name"`
+ // Details about the container's current condition.
+ // +optional
+ State ContainerState `json:"state,omitempty"`
+ // Details about the container's last termination condition.
+ // +optional
+ LastTerminationState ContainerState `json:"lastState,omitempty"`
+ // Specifies whether the container has passed its readiness probe.
+ Ready bool `json:"ready"`
+ // The number of times the container has been restarted, currently based on
+ // the number of dead containers that have not yet been removed.
+ // Note that this is calculated from dead containers. But those containers are subject to
+ // garbage collection. This value will get capped at 5 by GC.
+ RestartCount int32 `json:"restartCount"`
+ // The image the container is running.
+ // More info: https://kubernetes.io/docs/concepts/containers/images
+ // TODO(dchen1107): Which image the container is running with?
+ Image string `json:"image"`
+ // ImageID of the container's image.
+ ImageID string `json:"imageID"`
+ // Container's ID in the format 'docker://<container_id>'.
+ // +optional
+ ContainerID string `json:"containerID,omitempty"`
+ // Specifies whether the container has passed its startup probe.
+ // Initialized as false, becomes true after startupProbe is considered successful.
+ // Resets to false when the container is restarted, or if kubelet loses state temporarily.
+ // Is always true when no startupProbe is defined.
+ // +optional
+ Started *bool `json:"started,omitempty"`
+}
+
+// PodPhase is a label for the condition of a pod at the current time.
+type PodPhase string
+
+// These are the valid statuses of pods.
+const (
+ // PodPending 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.
+ PodPending PodPhase = "Pending"
+ // PodRunning 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.
+ PodRunning PodPhase = "Running"
+ // PodSucceeded 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.
+ PodSucceeded PodPhase = "Succeeded"
+ // PodFailed 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).
+ PodFailed PodPhase = "Failed"
+ // PodUnknown 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)
+ PodUnknown PodPhase = "Unknown"
+)
+
+// PodConditionType is a valid value for PodCondition.Type
+type PodConditionType string
+
+// These are valid conditions of pod.
+const (
+ // ContainersReady indicates whether all containers in the pod are ready.
+ ContainersReady PodConditionType = "ContainersReady"
+ // PodInitialized means that all init containers in the pod have started successfully.
+ PodInitialized PodConditionType = "Initialized"
+ // PodReady means the pod is able to service requests and should be added to the
+ // load balancing pools of all matching services.
+ PodReady PodConditionType = "Ready"
+ // PodScheduled represents status of the scheduling process for this pod.
+ PodScheduled PodConditionType = "PodScheduled"
+)
+
+// These are reasons for a pod's transition to a condition.
+const (
+ // PodReasonUnschedulable reason in PodScheduled PodCondition means that the scheduler
+ // can't schedule the pod right now, for example due to insufficient resources in the cluster.
+ PodReasonUnschedulable = "Unschedulable"
+)
+
+// PodCondition contains details for the current condition of this pod.
+type PodCondition struct {
+ // Type is the type of the condition.
+ // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions
+ Type PodConditionType `json:"type"`
+ // 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
+ Status ConditionStatus `json:"status"`
+ // Last time we probed the condition.
+ // +optional
+ LastProbeTime metav1.Time `json:"lastProbeTime,omitempty"`
+ // Last time the condition transitioned from one status to another.
+ // +optional
+ LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
+ // Unique, one-word, CamelCase reason for the condition's last transition.
+ // +optional
+ Reason string `json:"reason,omitempty"`
+ // Human-readable message indicating details about last transition.
+ // +optional
+ Message string `json:"message,omitempty"`
+}
+
+// RestartPolicy describes how the container should be restarted.
+// Only one of the following restart policies may be specified.
+// If none of the following policies is specified, the default one
+// is RestartPolicyAlways.
+type RestartPolicy string
+
+const (
+ RestartPolicyAlways RestartPolicy = "Always"
+ RestartPolicyOnFailure RestartPolicy = "OnFailure"
+ RestartPolicyNever RestartPolicy = "Never"
+)
+
+// DNSPolicy defines how a pod's DNS will be configured.
+type DNSPolicy string
+
+const (
+ // DNSClusterFirstWithHostNet indicates that the pod should use cluster DNS
+ // first, if it is available, then fall back on the default
+ // (as determined by kubelet) DNS settings.
+ DNSClusterFirstWithHostNet DNSPolicy = "ClusterFirstWithHostNet"
+
+ // DNSClusterFirst indicates that the pod should use cluster DNS
+ // first unless hostNetwork is true, if it is available, then
+ // fall back on the default (as determined by kubelet) DNS settings.
+ DNSClusterFirst DNSPolicy = "ClusterFirst"
+
+ // DNSDefault indicates that the pod should use the default (as
+ // determined by kubelet) DNS settings.
+ DNSDefault DNSPolicy = "Default"
+
+ // DNSNone indicates that the pod should use empty DNS settings. DNS
+ // parameters such as nameservers and search paths should be defined via
+ // DNSConfig.
+ DNSNone DNSPolicy = "None"
+)
+
+const (
+ // DefaultTerminationGracePeriodSeconds indicates the default duration in
+ // seconds a pod needs to terminate gracefully.
+ DefaultTerminationGracePeriodSeconds = 30
+)
+
+// A node selector represents the union of the results of one or more label queries
+// over a set of nodes; that is, it represents the OR of the selectors represented
+// by the node selector terms.
+// +structType=atomic
+type NodeSelector struct {
+ //Required. A list of node selector terms. The terms are ORed.
+ NodeSelectorTerms []NodeSelectorTerm `json:"nodeSelectorTerms"`
+}
+
+// A null or empty node selector term matches no objects. The requirements of
+// them are ANDed.
+// The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.
+// +structType=atomic
+type NodeSelectorTerm struct {
+ // A list of node selector requirements by node's labels.
+ // +optional
+ MatchExpressions []NodeSelectorRequirement `json:"matchExpressions,omitempty"`
+ // A list of node selector requirements by node's fields.
+ // +optional
+ MatchFields []NodeSelectorRequirement `json:"matchFields,omitempty"`
+}
+
+// A node selector requirement is a selector that contains values, a key, and an operator
+// that relates the key and values.
+type NodeSelectorRequirement struct {
+ // The label key that the selector applies to.
+ Key string `json:"key"`
+ // Represents a key's relationship to a set of values.
+ // Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ Operator NodeSelectorOperator `json:"operator"`
+ // An array of string values. If the operator is In or NotIn,
+ // the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ // the values array must be empty. If the operator is Gt or Lt, the values
+ // array must have a single element, which will be interpreted as an integer.
+ // This array is replaced during a strategic merge patch.
+ // +optional
+ Values []string `json:"values,omitempty"`
+}
+
+// A node selector operator is the set of operators that can be used in
+// a node selector requirement.
+type NodeSelectorOperator string
+
+const (
+ NodeSelectorOpIn NodeSelectorOperator = "In"
+ NodeSelectorOpNotIn NodeSelectorOperator = "NotIn"
+ NodeSelectorOpExists NodeSelectorOperator = "Exists"
+ NodeSelectorOpDoesNotExist NodeSelectorOperator = "DoesNotExist"
+ NodeSelectorOpGt NodeSelectorOperator = "Gt"
+ NodeSelectorOpLt NodeSelectorOperator = "Lt"
+)
+
+// A topology selector term represents the result of label queries.
+// A null or empty topology selector term matches no objects.
+// The requirements of them are ANDed.
+// It provides a subset of functionality as NodeSelectorTerm.
+// This is an alpha feature and may change in the future.
+// +structType=atomic
+type TopologySelectorTerm struct {
+ // Usage: Fields of type []TopologySelectorTerm must be listType=atomic.
+
+ // A list of topology selector requirements by labels.
+ // +optional
+ MatchLabelExpressions []TopologySelectorLabelRequirement `json:"matchLabelExpressions,omitempty"`
+}
+
+// A topology selector requirement is a selector that matches given label.
+// This is an alpha feature and may change in the future.
+type TopologySelectorLabelRequirement struct {
+ // The label key that the selector applies to.
+ Key string `json:"key"`
+ // An array of string values. One value must match the label to be selected.
+ // Each entry in Values is ORed.
+ Values []string `json:"values"`
+}
+
+// Affinity is a group of affinity scheduling rules.
+type Affinity struct {
+ // Describes node affinity scheduling rules for the pod.
+ // +optional
+ NodeAffinity *NodeAffinity `json:"nodeAffinity,omitempty"`
+ // Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)).
+ // +optional
+ PodAffinity *PodAffinity `json:"podAffinity,omitempty"`
+ // Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)).
+ // +optional
+ PodAntiAffinity *PodAntiAffinity `json:"podAntiAffinity,omitempty"`
+}
+
+// Pod affinity is a group of inter pod affinity scheduling rules.
+type PodAffinity struct {
+ // NOT YET IMPLEMENTED. TODO: Uncomment field once it is implemented.
+ // If the affinity requirements specified by this field are not met at
+ // scheduling time, the pod will not be scheduled onto the node.
+ // If the affinity requirements specified by this field cease to be met
+ // at some point during pod execution (e.g. due to a pod label update), the
+ // system will try to eventually evict the pod from its node.
+ // When there are multiple elements, the lists of nodes corresponding to each
+ // podAffinityTerm are intersected, i.e. all terms must be satisfied.
+ // +optional
+ // RequiredDuringSchedulingRequiredDuringExecution []PodAffinityTerm `json:"requiredDuringSchedulingRequiredDuringExecution,omitempty"`
+
+ // If the affinity requirements specified by this field are not met at
+ // scheduling time, the pod will not be scheduled onto the node.
+ // If the affinity requirements specified by this field cease to be met
+ // at some point during pod execution (e.g. due to a pod label update), the
+ // system may or may not try to eventually evict the pod from its node.
+ // When there are multiple elements, the lists of nodes corresponding to each
+ // podAffinityTerm are intersected, i.e. all terms must be satisfied.
+ // +optional
+ RequiredDuringSchedulingIgnoredDuringExecution []PodAffinityTerm `json:"requiredDuringSchedulingIgnoredDuringExecution,omitempty"`
+ // The scheduler will prefer to schedule pods to nodes that satisfy
+ // the affinity expressions specified by this field, but it may choose
+ // a node that violates one or more of the expressions. The node that is
+ // most preferred is the one with the greatest sum of weights, i.e.
+ // for each node that meets all of the scheduling requirements (resource
+ // request, requiredDuringScheduling affinity expressions, etc.),
+ // compute a sum by iterating through the elements of this field and adding
+ // "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ // node(s) with the highest sum are the most preferred.
+ // +optional
+ PreferredDuringSchedulingIgnoredDuringExecution []WeightedPodAffinityTerm `json:"preferredDuringSchedulingIgnoredDuringExecution,omitempty"`
+}
+
+// Pod anti affinity is a group of inter pod anti affinity scheduling rules.
+type PodAntiAffinity struct {
+ // NOT YET IMPLEMENTED. TODO: Uncomment field once it is implemented.
+ // If the anti-affinity requirements specified by this field are not met at
+ // scheduling time, the pod will not be scheduled onto the node.
+ // If the anti-affinity requirements specified by this field cease to be met
+ // at some point during pod execution (e.g. due to a pod label update), the
+ // system will try to eventually evict the pod from its node.
+ // When there are multiple elements, the lists of nodes corresponding to each
+ // podAffinityTerm are intersected, i.e. all terms must be satisfied.
+ // +optional
+ // RequiredDuringSchedulingRequiredDuringExecution []PodAffinityTerm `json:"requiredDuringSchedulingRequiredDuringExecution,omitempty"`
+
+ // If the anti-affinity requirements specified by this field are not met at
+ // scheduling time, the pod will not be scheduled onto the node.
+ // If the anti-affinity requirements specified by this field cease to be met
+ // at some point during pod execution (e.g. due to a pod label update), the
+ // system may or may not try to eventually evict the pod from its node.
+ // When there are multiple elements, the lists of nodes corresponding to each
+ // podAffinityTerm are intersected, i.e. all terms must be satisfied.
+ // +optional
+ RequiredDuringSchedulingIgnoredDuringExecution []PodAffinityTerm `json:"requiredDuringSchedulingIgnoredDuringExecution,omitempty"`
+ // The scheduler will prefer to schedule pods to nodes that satisfy
+ // the anti-affinity expressions specified by this field, but it may choose
+ // a node that violates one or more of the expressions. The node that is
+ // most preferred is the one with the greatest sum of weights, i.e.
+ // for each node that meets all of the scheduling requirements (resource
+ // request, requiredDuringScheduling anti-affinity expressions, etc.),
+ // compute a sum by iterating through the elements of this field and adding
+ // "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ // node(s) with the highest sum are the most preferred.
+ // +optional
+ PreferredDuringSchedulingIgnoredDuringExecution []WeightedPodAffinityTerm `json:"preferredDuringSchedulingIgnoredDuringExecution,omitempty"`
+}
+
+// The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s)
+type WeightedPodAffinityTerm struct {
+ // weight associated with matching the corresponding podAffinityTerm,
+ // in the range 1-100.
+ Weight int32 `json:"weight"`
+ // Required. A pod affinity term, associated with the corresponding weight.
+ PodAffinityTerm PodAffinityTerm `json:"podAffinityTerm"`
+}
+
+// Defines a set of pods (namely those matching the labelSelector
+// relative to the given namespace(s)) that this pod should be
+// co-located (affinity) or not co-located (anti-affinity) with,
+// where co-located is defined as running on a node whose value of
+// the label with key <topologyKey> matches that of any node on which
+// a pod of the set of pods is running
+type PodAffinityTerm struct {
+ // A label query over a set of resources, in this case pods.
+ // +optional
+ LabelSelector *metav1.LabelSelector `json:"labelSelector,omitempty"`
+ // namespaces specifies a static list of namespace names that the term applies to.
+ // The term is applied to the union of the namespaces listed in this field
+ // and the ones selected by namespaceSelector.
+ // null or empty namespaces list and null namespaceSelector means "this pod's namespace"
+ // +optional
+ Namespaces []string `json:"namespaces,omitempty"`
+ // This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ // the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ // whose value of the label with key topologyKey matches that of any node on which any of the
+ // selected pods is running.
+ // Empty topologyKey is not allowed.
+ TopologyKey string `json:"topologyKey"`
+ // A label query over the set of namespaces that the term applies to.
+ // The term is applied to the union of the namespaces selected by this field
+ // and the ones listed in the namespaces field.
+ // null selector and null or empty namespaces list means "this pod's namespace".
+ // An empty selector ({}) matches all namespaces.
+ // This field is beta-level and is only honored when PodAffinityNamespaceSelector feature is enabled.
+ // +optional
+ NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty"`
+}
+
+// Node affinity is a group of node affinity scheduling rules.
+type NodeAffinity struct {
+ // NOT YET IMPLEMENTED. TODO: Uncomment field once it is implemented.
+ // If the affinity requirements specified by this field are not met at
+ // scheduling time, the pod will not be scheduled onto the node.
+ // If the affinity requirements specified by this field cease to be met
+ // at some point during pod execution (e.g. due to an update), the system
+ // will try to eventually evict the pod from its node.
+ // +optional
+ // RequiredDuringSchedulingRequiredDuringExecution *NodeSelector `json:"requiredDuringSchedulingRequiredDuringExecution,omitempty"`
+
+ // If the affinity requirements specified by this field are not met at
+ // scheduling time, the pod will not be scheduled onto the node.
+ // If the affinity requirements specified by this field cease to be met
+ // at some point during pod execution (e.g. due to an update), the system
+ // may or may not try to eventually evict the pod from its node.
+ // +optional
+ RequiredDuringSchedulingIgnoredDuringExecution *NodeSelector `json:"requiredDuringSchedulingIgnoredDuringExecution,omitempty"`
+ // The scheduler will prefer to schedule pods to nodes that satisfy
+ // the affinity expressions specified by this field, but it may choose
+ // a node that violates one or more of the expressions. The node that is
+ // most preferred is the one with the greatest sum of weights, i.e.
+ // for each node that meets all of the scheduling requirements (resource
+ // request, requiredDuringScheduling affinity expressions, etc.),
+ // compute a sum by iterating through the elements of this field and adding
+ // "weight" to the sum if the node matches the corresponding matchExpressions; the
+ // node(s) with the highest sum are the most preferred.
+ // +optional
+ PreferredDuringSchedulingIgnoredDuringExecution []PreferredSchedulingTerm `json:"preferredDuringSchedulingIgnoredDuringExecution,omitempty"`
+}
+
+// An empty preferred scheduling term matches all objects with implicit weight 0
+// (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op).
+type PreferredSchedulingTerm struct {
+ // Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100.
+ Weight int32 `json:"weight"`
+ // A node selector term, associated with the corresponding weight.
+ Preference NodeSelectorTerm `json:"preference"`
+}
+
+// PodReadinessGate contains the reference to a pod condition
+type PodReadinessGate struct {
+ // ConditionType refers to a condition in the pod's condition list with matching type.
+ ConditionType PodConditionType `json:"conditionType"`
+}
+
+// PodSpec is a description of a pod.
+type PodSpec struct {
+ // List of volumes that can be mounted by containers belonging to the pod.
+ // More info: https://kubernetes.io/docs/concepts/storage/volumes
+ // +optional
+ // +patchMergeKey=name
+ // +patchStrategy=merge,retainKeys
+ Volumes []Volume `json:"volumes,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name"`
+ // List of initialization containers belonging to the pod.
+ // Init containers are executed in order prior to containers being started. If any
+ // init container fails, the pod is considered to have failed and is handled according
+ // to its restartPolicy. The name for an init container or normal container must be
+ // unique among all containers.
+ // Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes.
+ // The resourceRequirements of an init container are taken into account during scheduling
+ // by finding the highest request/limit for each resource type, and then using the max of
+ // of that value or the sum of the normal containers. Limits are applied to init containers
+ // in a similar fashion.
+ // Init containers cannot currently be added or removed.
+ // Cannot be updated.
+ // More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/
+ // +patchMergeKey=name
+ // +patchStrategy=merge
+ InitContainers []Container `json:"initContainers,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
+ // List of containers belonging to the pod.
+ // Containers cannot currently be added or removed.
+ // There must be at least one container in a Pod.
+ // Cannot be updated.
+ // +patchMergeKey=name
+ // +patchStrategy=merge
+ Containers []Container `json:"containers" patchStrategy:"merge" patchMergeKey:"name"`
+ // List of ephemeral containers run in this pod. Ephemeral containers may be run in an existing
+ // pod to perform user-initiated actions such as debugging. This list cannot be specified when
+ // creating a pod, and it cannot be modified by updating the pod spec. In order to add an
+ // ephemeral container to an existing pod, use the pod's ephemeralcontainers subresource.
+ // This field is alpha-level and is only honored by servers that enable the EphemeralContainers feature.
+ // +optional
+ // +patchMergeKey=name
+ // +patchStrategy=merge
+ EphemeralContainers []EphemeralContainer `json:"ephemeralContainers,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
+ // Restart policy for all containers within the pod.
+ // One of Always, OnFailure, Never.
+ // Default to Always.
+ // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy
+ // +optional
+ RestartPolicy RestartPolicy `json:"restartPolicy,omitempty"`
+ // Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request.
+ // Value must be non-negative integer. The value zero indicates stop immediately via
+ // the kill signal (no opportunity to shut down).
+ // If this value is nil, the default grace period will be used instead.
+ // The grace period is the duration in seconds after the processes running in the pod are sent
+ // a termination signal and the time when the processes are forcibly halted with a kill signal.
+ // Set this value longer than the expected cleanup time for your process.
+ // Defaults to 30 seconds.
+ // +optional
+ TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"`
+ // Optional duration in seconds the pod may be active on the node relative to
+ // StartTime before the system will actively try to mark it failed and kill associated containers.
+ // Value must be a positive integer.
+ // +optional
+ ActiveDeadlineSeconds *int64 `json:"activeDeadlineSeconds,omitempty"`
+ // Set DNS policy for the pod.
+ // Defaults to "ClusterFirst".
+ // Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'.
+ // DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy.
+ // To have DNS options set along with hostNetwork, you have to specify DNS policy
+ // explicitly to 'ClusterFirstWithHostNet'.
+ // +optional
+ DNSPolicy DNSPolicy `json:"dnsPolicy,omitempty"`
+ // NodeSelector is a selector which must be true for the pod to fit on a node.
+ // Selector which must match a node's labels for the pod to be scheduled on that node.
+ // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
+ // +optional
+ // +mapType=atomic
+ NodeSelector map[string]string `json:"nodeSelector,omitempty"`
+
+ // 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/
+ // +optional
+ ServiceAccountName string `json:"serviceAccountName,omitempty"`
+ // DeprecatedServiceAccount is a depreciated alias for ServiceAccountName.
+ // Deprecated: Use serviceAccountName instead.
+ // +k8s:conversion-gen=false
+ // +optional
+ DeprecatedServiceAccount string `json:"serviceAccount,omitempty"`
+ // AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.
+ // +optional
+ AutomountServiceAccountToken *bool `json:"automountServiceAccountToken,omitempty"`
+
+ // NodeName is a request to schedule this pod onto a specific node. If it is non-empty,
+ // the scheduler simply schedules this pod onto that node, assuming that it fits resource
+ // requirements.
+ // +optional
+ NodeName string `json:"nodeName,omitempty"`
+ // Host networking requested for this pod. Use the host's network namespace.
+ // If this option is set, the ports that will be used must be specified.
+ // Default to false.
+ // +k8s:conversion-gen=false
+ // +optional
+ HostNetwork bool `json:"hostNetwork,omitempty"`
+ // Use the host's pid namespace.
+ // Optional: Default to false.
+ // +k8s:conversion-gen=false
+ // +optional
+ HostPID bool `json:"hostPID,omitempty"`
+ // Use the host's ipc namespace.
+ // Optional: Default to false.
+ // +k8s:conversion-gen=false
+ // +optional
+ HostIPC bool `json:"hostIPC,omitempty"`
+ // Share a single process namespace between all of the containers in a pod.
+ // When this is set containers will be able to view and signal processes from other containers
+ // in the same pod, and the first process in each container will not be assigned PID 1.
+ // HostPID and ShareProcessNamespace cannot both be set.
+ // Optional: Default to false.
+ // +k8s:conversion-gen=false
+ // +optional
+ ShareProcessNamespace *bool `json:"shareProcessNamespace,omitempty"`
+ // SecurityContext holds pod-level security attributes and common container settings.
+ // Optional: Defaults to empty. See type description for default values of each field.
+ // +optional
+ SecurityContext *PodSecurityContext `json:"securityContext,omitempty"`
+ // 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. For example,
+ // in the case of docker, only DockerConfig type secrets are honored.
+ // More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod
+ // +optional
+ // +patchMergeKey=name
+ // +patchStrategy=merge
+ ImagePullSecrets []LocalObjectReference `json:"imagePullSecrets,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
+ // Specifies the hostname of the Pod
+ // If not specified, the pod's hostname will be set to a system-defined value.
+ // +optional
+ Hostname string `json:"hostname,omitempty"`
+ // If specified, the fully qualified Pod hostname will be "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>".
+ // If not specified, the pod will not have a domainname at all.
+ // +optional
+ Subdomain string `json:"subdomain,omitempty"`
+ // If specified, the pod's scheduling constraints
+ // +optional
+ Affinity *Affinity `json:"affinity,omitempty"`
+ // If specified, the pod will be dispatched by specified scheduler.
+ // If not specified, the pod will be dispatched by default scheduler.
+ // +optional
+ SchedulerName string `json:"schedulerName,omitempty"`
+ // HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts
+ // file if specified. This is only valid for non-hostNetwork pods.
+ // +optional
+ // +patchMergeKey=ip
+ // +patchStrategy=merge
+ HostAliases []HostAlias `json:"hostAliases,omitempty" patchStrategy:"merge" patchMergeKey:"ip"`
+ // If specified, indicates the pod's priority. "system-node-critical" and
+ // "system-cluster-critical" are two special keywords which indicate the
+ // highest priorities with the former being the highest priority. Any other
+ // name must be defined by creating a PriorityClass object with that name.
+ // If not specified, the pod priority will be default or zero if there is no
+ // default.
+ // +optional
+ PriorityClassName string `json:"priorityClassName,omitempty"`
+ // The priority value. Various system components use this field to find the
+ // priority of the pod. When Priority Admission Controller is enabled, it
+ // prevents users from setting this field. The admission controller populates
+ // this field from PriorityClassName.
+ // The higher the value, the higher the priority.
+ // +optional
+ Priority *int32 `json:"priority,omitempty"`
+ // Specifies the DNS parameters of a pod.
+ // Parameters specified here will be merged to the generated DNS
+ // configuration based on DNSPolicy.
+ // +optional
+ DNSConfig *PodDNSConfig `json:"dnsConfig,omitempty"`
+ // If specified, all readiness gates will be evaluated for pod readiness.
+ // A pod is ready when all its containers are ready AND
+ // all conditions specified in the readiness gates have status equal to "True"
+ // More info: https://git.k8s.io/enhancements/keps/sig-network/580-pod-readiness-gates
+ // +optional
+ ReadinessGates []PodReadinessGate `json:"readinessGates,omitempty"`
+ // 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
+ // This is a beta feature as of Kubernetes v1.14.
+ // +optional
+ RuntimeClassName *string `json:"runtimeClassName,omitempty"`
+ // EnableServiceLinks indicates whether information about services should be injected into pod's
+ // environment variables, matching the syntax of Docker links.
+ // Optional: Defaults to true.
+ // +optional
+ EnableServiceLinks *bool `json:"enableServiceLinks,omitempty"`
+ // PreemptionPolicy is the Policy for preempting pods with lower priority.
+ // One of Never, PreemptLowerPriority.
+ // Defaults to PreemptLowerPriority if unset.
+ // This field is beta-level, gated by the NonPreemptingPriority feature-gate.
+ // +optional
+ PreemptionPolicy *PreemptionPolicy `json:"preemptionPolicy,omitempty"`
+ // Overhead represents the resource overhead associated with running a pod for a given RuntimeClass.
+ // This field will be autopopulated at admission time by the RuntimeClass admission controller. If
+ // the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests.
+ // The RuntimeClass admission controller will reject Pod create requests which have the overhead already
+ // set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value
+ // defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero.
+ // More info: https://git.k8s.io/enhancements/keps/sig-node/688-pod-overhead/README.md
+ // This field is beta-level as of Kubernetes v1.18, and is only honored by servers that enable the PodOverhead feature.
+ // +optional
+ Overhead ResourceList `json:"overhead,omitempty"`
+ // 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.
+ // +optional
+ // +patchMergeKey=topologyKey
+ // +patchStrategy=merge
+ // +listType=map
+ // +listMapKey=topologyKey
+ // +listMapKey=whenUnsatisfiable
+ TopologySpreadConstraints []TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty" patchStrategy:"merge" patchMergeKey:"topologyKey"`
+ // If true the pod's hostname will be configured as the pod's FQDN, rather than the leaf name (the default).
+ // In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname).
+ // In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters to FQDN.
+ // If a pod does not have FQDN, this has no effect.
+ // Default to false.
+ // +optional
+ SetHostnameAsFQDN *bool `json:"setHostnameAsFQDN,omitempty"`
+}
+
+type UnsatisfiableConstraintAction string
+
+const (
+ // DoNotSchedule instructs the scheduler not to schedule the pod
+ // when constraints are not satisfied.
+ DoNotSchedule UnsatisfiableConstraintAction = "DoNotSchedule"
+ // ScheduleAnyway instructs the scheduler to schedule the pod
+ // even if constraints are not satisfied.
+ ScheduleAnyway UnsatisfiableConstraintAction = "ScheduleAnyway"
+)
+
+// TopologySpreadConstraint specifies how to spread matching pods among the given topology.
+type TopologySpreadConstraint struct {
+ // MaxSkew describes the degree to which pods may be unevenly distributed.
+ // When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference
+ // between the number of matching pods in the target topology and the global minimum.
+ // For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same
+ // labelSelector spread as 1/1/0:
+ // +-------+-------+-------+
+ // | zone1 | zone2 | zone3 |
+ // +-------+-------+-------+
+ // | P | P | |
+ // +-------+-------+-------+
+ // - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 1/1/1;
+ // scheduling it onto zone1(zone2) would make the ActualSkew(2-0) on zone1(zone2)
+ // violate MaxSkew(1).
+ // - if MaxSkew is 2, incoming pod can be scheduled onto any zone.
+ // When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence
+ // to topologies that satisfy it.
+ // It's a required field. Default value is 1 and 0 is not allowed.
+ MaxSkew int32 `json:"maxSkew"`
+ // TopologyKey is the key of node labels. Nodes that have a label with this key
+ // and identical values are considered to be in the same topology.
+ // We consider each <key, value> as a "bucket", and try to put balanced number
+ // of pods into each bucket.
+ // It's a required field.
+ TopologyKey string `json:"topologyKey"`
+ // WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy
+ // the spread constraint.
+ // - DoNotSchedule (default) tells the scheduler not to schedule it.
+ // - ScheduleAnyway tells the scheduler to schedule the pod in any location,
+ // but giving higher precedence to topologies that would help reduce the
+ // skew.
+ // A constraint is considered "Unsatisfiable" for an incoming pod
+ // if and only if every possible node assigment for that pod would violate
+ // "MaxSkew" on some topology.
+ // For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same
+ // labelSelector spread as 3/1/1:
+ // +-------+-------+-------+
+ // | zone1 | zone2 | zone3 |
+ // +-------+-------+-------+
+ // | P P P | P | P |
+ // +-------+-------+-------+
+ // If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled
+ // to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies
+ // MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler
+ // won't make it *more* imbalanced.
+ // It's a required field.
+ WhenUnsatisfiable UnsatisfiableConstraintAction `json:"whenUnsatisfiable"`
+ // LabelSelector is used to find matching pods.
+ // Pods that match this label selector are counted to determine the number of pods
+ // in their corresponding topology domain.
+ // +optional
+ LabelSelector *metav1.LabelSelector `json:"labelSelector,omitempty"`
+}
+
+const (
+ // The default value for enableServiceLinks attribute.
+ DefaultEnableServiceLinks = true
+)
+
+// HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the
+// pod's hosts file.
+type HostAlias struct {
+ // IP address of the host file entry.
+ IP string `json:"ip,omitempty"`
+ // Hostnames for the above IP address.
+ Hostnames []string `json:"hostnames,omitempty"`
+}
+
+// PodFSGroupChangePolicy holds policies that will be used for applying fsGroup to a volume
+// when volume is mounted.
+type PodFSGroupChangePolicy string
+
+const (
+ // FSGroupChangeOnRootMismatch indicates that volume's ownership and permissions will be changed
+ // only when permission and ownership of root directory does not match with expected
+ // permissions on the volume. This can help shorten the time it takes to change
+ // ownership and permissions of a volume.
+ FSGroupChangeOnRootMismatch PodFSGroupChangePolicy = "OnRootMismatch"
+ // FSGroupChangeAlways indicates that volume's ownership and permissions
+ // should always be changed whenever volume is mounted inside a Pod. This the default
+ // behavior.
+ FSGroupChangeAlways PodFSGroupChangePolicy = "Always"
+)
+
+// 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 PodSecurityContext struct {
+ // The SELinux context to be applied to all containers.
+ // If unspecified, the container runtime will allocate a random SELinux context for each
+ // container. May also be set in SecurityContext. If set in
+ // both SecurityContext and PodSecurityContext, the value specified in SecurityContext
+ // takes precedence for that container.
+ // +optional
+ SELinuxOptions *SELinuxOptions `json:"seLinuxOptions,omitempty"`
+ // The UID to run the entrypoint of the container process.
+ // Defaults to user specified in image metadata if unspecified.
+ // May also be set in SecurityContext. If set in both SecurityContext and
+ // PodSecurityContext, the value specified in SecurityContext takes precedence
+ // for that container.
+ // +optional
+ RunAsUser *int64 `json:"runAsUser,omitempty"`
+ // The GID to run the entrypoint of the container process.
+ // Uses runtime default if unset.
+ // May also be set in SecurityContext. If set in both SecurityContext and
+ // PodSecurityContext, the value specified in SecurityContext takes precedence
+ // for that container.
+ // +optional
+ RunAsGroup *int64 `json:"runAsGroup,omitempty"`
+ // 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 SecurityContext. If set in both SecurityContext and
+ // PodSecurityContext, the value specified in SecurityContext takes precedence.
+ // +optional
+ RunAsNonRoot *bool `json:"runAsNonRoot,omitempty"`
+ // A list of groups applied to the first process run in each container, in addition
+ // to the container's primary GID. If unspecified, no groups will be added to
+ // any container.
+ // +optional
+ SupplementalGroups []int64 `json:"supplementalGroups,omitempty"`
+ // A special supplemental group that applies to all containers in a pod.
+ // Some volume types allow the Kubelet to change the ownership of that volume
+ // to be owned by the pod:
+ //
+ // 1. The owning GID will be the FSGroup
+ // 2. The setgid bit is set (new files created in the volume will be owned by FSGroup)
+ // 3. The permission bits are OR'd with rw-rw----
+ //
+ // If unset, the Kubelet will not modify the ownership and permissions of any volume.
+ // +optional
+ FSGroup *int64 `json:"fsGroup,omitempty"`
+ // Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported
+ // sysctls (by the container runtime) might fail to launch.
+ // +optional
+ Sysctls []Sysctl `json:"sysctls,omitempty"`
+ // fsGroupChangePolicy defines behavior of changing ownership and permission of the volume
+ // before being exposed inside Pod. This field will only apply to
+ // volume types which support fsGroup based ownership(and permissions).
+ // It will have no effect on ephemeral volume types such as: secret, configmaps
+ // and emptydir.
+ // Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used.
+ // +optional
+ FSGroupChangePolicy *PodFSGroupChangePolicy `json:"fsGroupChangePolicy,omitempty"`
+ // The seccomp options to use by the containers in this pod.
+ // +optional
+ SeccompProfile *SeccompProfile `json:"seccompProfile,omitempty"`
+}
+
+// SeccompProfile defines a pod/container's seccomp profile settings.
+// Only one profile source may be set.
+// +union
+type SeccompProfile struct {
+ // type indicates which kind of seccomp profile will be applied.
+ // Valid options are:
+ //
+ // Localhost - a profile defined in a file on the node should be used.
+ // RuntimeDefault - the container runtime default profile should be used.
+ // Unconfined - no profile should be applied.
+ // +unionDiscriminator
+ Type SeccompProfileType `json:"type"`
+ // localhostProfile indicates a profile defined in a file on the node should be used.
+ // The profile must be preconfigured on the node to work.
+ // Must be a descending path, relative to the kubelet's configured seccomp profile location.
+ // Must only be set if type is "Localhost".
+ // +optional
+ LocalhostProfile *string `json:"localhostProfile,omitempty"`
+}
+
+// SeccompProfileType defines the supported seccomp profile types.
+type SeccompProfileType string
+
+const (
+ // SeccompProfileTypeUnconfined indicates no seccomp profile is applied (A.K.A. unconfined).
+ SeccompProfileTypeUnconfined SeccompProfileType = "Unconfined"
+ // SeccompProfileTypeRuntimeDefault represents the default container runtime seccomp profile.
+ SeccompProfileTypeRuntimeDefault SeccompProfileType = "RuntimeDefault"
+ // SeccompProfileTypeLocalhost indicates a profile defined in a file on the node should be used.
+ // The file's location is based off the kubelet's deprecated flag --seccomp-profile-root.
+ // Once the flag support is removed the location will be <kubelet-root-dir>/seccomp.
+ SeccompProfileTypeLocalhost SeccompProfileType = "Localhost"
+)
+
+// PodQOSClass defines the supported qos classes of Pods.
+type PodQOSClass string
+
+const (
+ // PodQOSGuaranteed is the Guaranteed qos class.
+ PodQOSGuaranteed PodQOSClass = "Guaranteed"
+ // PodQOSBurstable is the Burstable qos class.
+ PodQOSBurstable PodQOSClass = "Burstable"
+ // PodQOSBestEffort is the BestEffort qos class.
+ PodQOSBestEffort PodQOSClass = "BestEffort"
+)
+
+// PodDNSConfig defines the DNS parameters of a pod in addition to
+// those generated from DNSPolicy.
+type PodDNSConfig struct {
+ // A list of DNS name server IP addresses.
+ // This will be appended to the base nameservers generated from DNSPolicy.
+ // Duplicated nameservers will be removed.
+ // +optional
+ Nameservers []string `json:"nameservers,omitempty"`
+ // A list of DNS search domains for host-name lookup.
+ // This will be appended to the base search paths generated from DNSPolicy.
+ // Duplicated search paths will be removed.
+ // +optional
+ Searches []string `json:"searches,omitempty"`
+ // A list of DNS resolver options.
+ // This will be merged with the base options generated from DNSPolicy.
+ // Duplicated entries will be removed. Resolution options given in Options
+ // will override those that appear in the base DNSPolicy.
+ // +optional
+ Options []PodDNSConfigOption `json:"options,omitempty"`
+}
+
+// PodDNSConfigOption defines DNS resolver options of a pod.
+type PodDNSConfigOption struct {
+ // Required.
+ Name string `json:"name,omitempty"`
+ // +optional
+ Value *string `json:"value,omitempty"`
+}
+
+// IP address information for entries in the (plural) PodIPs field.
+// Each entry includes:
+// IP: An IP address allocated to the pod. Routable at least within the cluster.
+type PodIP struct {
+ // ip is an IP address (IPv4 or IPv6) assigned to the pod
+ IP string `json:"ip,omitempty"`
+}
+
+// EphemeralContainerCommon is a copy of all fields in Container to be inlined in
+// EphemeralContainer. This separate type allows easy conversion from EphemeralContainer
+// to Container and allows separate documentation for the fields of EphemeralContainer.
+// When a new field is added to Container it must be added here as well.
+type EphemeralContainerCommon struct {
+ // Name of the ephemeral container specified as a DNS_LABEL.
+ // This name must be unique among all containers, init containers and ephemeral containers.
+ Name string `json:"name"`
+ // Docker image name.
+ // More info: https://kubernetes.io/docs/concepts/containers/images
+ Image string `json:"image,omitempty"`
+ // Entrypoint array. Not executed within a shell.
+ // The docker image's ENTRYPOINT is used if this is not provided.
+ // Variable references $(VAR_NAME) are expanded using the container's environment. If a variable
+ // cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced
+ // to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will
+ // produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless
+ // of whether the variable exists or not. Cannot be updated.
+ // More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
+ // +optional
+ Command []string `json:"command,omitempty"`
+ // Arguments to the entrypoint.
+ // The docker image's CMD is used if this is not provided.
+ // Variable references $(VAR_NAME) are expanded using the container's environment. If a variable
+ // cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced
+ // to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will
+ // produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless
+ // of whether the variable exists or not. Cannot be updated.
+ // More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
+ // +optional
+ Args []string `json:"args,omitempty"`
+ // Container's working directory.
+ // If not specified, the container runtime's default will be used, which
+ // might be configured in the container image.
+ // Cannot be updated.
+ // +optional
+ WorkingDir string `json:"workingDir,omitempty"`
+ // Ports are not allowed for ephemeral containers.
+ Ports []ContainerPort `json:"ports,omitempty"`
+ // List of sources to populate environment variables in the container.
+ // The keys defined within a source must be a C_IDENTIFIER. All invalid keys
+ // will be reported as an event when the container is starting. When a key exists in multiple
+ // sources, the value associated with the last source will take precedence.
+ // Values defined by an Env with a duplicate key will take precedence.
+ // Cannot be updated.
+ // +optional
+ EnvFrom []EnvFromSource `json:"envFrom,omitempty"`
+ // List of environment variables to set in the container.
+ // Cannot be updated.
+ // +optional
+ // +patchMergeKey=name
+ // +patchStrategy=merge
+ Env []EnvVar `json:"env,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
+ // Resources are not allowed for ephemeral containers. Ephemeral containers use spare resources
+ // already allocated to the pod.
+ // +optional
+ Resources ResourceRequirements `json:"resources,omitempty"`
+ // Pod volumes to mount into the container's filesystem.
+ // Cannot be updated.
+ // +optional
+ // +patchMergeKey=mountPath
+ // +patchStrategy=merge
+ VolumeMounts []VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath"`
+ // volumeDevices is the list of block devices to be used by the container.
+ // +patchMergeKey=devicePath
+ // +patchStrategy=merge
+ // +optional
+ VolumeDevices []VolumeDevice `json:"volumeDevices,omitempty" patchStrategy:"merge" patchMergeKey:"devicePath"`
+ // Probes are not allowed for ephemeral containers.
+ // +optional
+ LivenessProbe *Probe `json:"livenessProbe,omitempty"`
+ // Probes are not allowed for ephemeral containers.
+ // +optional
+ ReadinessProbe *Probe `json:"readinessProbe,omitempty"`
+ // Probes are not allowed for ephemeral containers.
+ // +optional
+ StartupProbe *Probe `json:"startupProbe,omitempty"`
+ // Lifecycle is not allowed for ephemeral containers.
+ // +optional
+ Lifecycle *Lifecycle `json:"lifecycle,omitempty"`
+ // Optional: Path at which the file to which the container's termination message
+ // will be written is mounted into the container's filesystem.
+ // Message written is intended to be brief final status, such as an assertion failure message.
+ // Will be truncated by the node if greater than 4096 bytes. The total message length across
+ // all containers will be limited to 12kb.
+ // Defaults to /dev/termination-log.
+ // Cannot be updated.
+ // +optional
+ TerminationMessagePath string `json:"terminationMessagePath,omitempty"`
+ // Indicate how the termination message should be populated. File will use the contents of
+ // terminationMessagePath to populate the container status message on both success and failure.
+ // FallbackToLogsOnError will use the last chunk of container log output if the termination
+ // message file is empty and the container exited with an error.
+ // The log output is limited to 2048 bytes or 80 lines, whichever is smaller.
+ // Defaults to File.
+ // Cannot be updated.
+ // +optional
+ TerminationMessagePolicy TerminationMessagePolicy `json:"terminationMessagePolicy,omitempty"`
+ // Image pull policy.
+ // One of Always, Never, IfNotPresent.
+ // Defaults to Always if :latest tag is specified, or IfNotPresent otherwise.
+ // Cannot be updated.
+ // More info: https://kubernetes.io/docs/concepts/containers/images#updating-images
+ // +optional
+ ImagePullPolicy PullPolicy `json:"imagePullPolicy,omitempty"`
+ // Optional: SecurityContext defines the security options the ephemeral container should be run with.
+ // If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext.
+ // +optional
+ SecurityContext *SecurityContext `json:"securityContext,omitempty"`
+
+ // Variables for interactive containers, these have very specialized use-cases (e.g. debugging)
+ // and shouldn't be used for general purpose containers.
+
+ // Whether this container should allocate a buffer for stdin in the container runtime. If this
+ // is not set, reads from stdin in the container will always result in EOF.
+ // Default is false.
+ // +optional
+ Stdin bool `json:"stdin,omitempty"`
+ // Whether the container runtime should close the stdin channel after it has been opened by
+ // a single attach. When stdin is true the stdin stream will remain open across multiple attach
+ // sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the
+ // first client attaches to stdin, and then remains open and accepts data until the client disconnects,
+ // at which time stdin is closed and remains closed until the container is restarted. If this
+ // flag is false, a container processes that reads from stdin will never receive an EOF.
+ // Default is false
+ // +optional
+ StdinOnce bool `json:"stdinOnce,omitempty"`
+ // Whether this container should allocate a TTY for itself, also requires 'stdin' to be true.
+ // Default is false.
+ // +optional
+ TTY bool `json:"tty,omitempty"`
+}
+
+// EphemeralContainerCommon converts to Container. All fields must be kept in sync between
+// these two types.
+var _ = Container(EphemeralContainerCommon{})
+
+// An EphemeralContainer is a container that may be added temporarily to an existing pod for
+// user-initiated activities such as debugging. Ephemeral containers have no resource or
+// scheduling guarantees, and they will not be restarted when they exit or when a pod is
+// removed or restarted. If an ephemeral container causes a pod to exceed its resource
+// allocation, the pod may be evicted.
+// Ephemeral containers may not be added by directly updating the pod spec. They must be added
+// via the pod's ephemeralcontainers subresource, and they will appear in the pod spec
+// once added.
+// This is an alpha feature enabled by the EphemeralContainers feature flag.
+type EphemeralContainer struct {
+ // Ephemeral containers have all of the fields of Container, plus additional fields
+ // specific to ephemeral containers. Fields in common with Container are in the
+ // following inlined struct so than an EphemeralContainer may easily be converted
+ // to a Container.
+ EphemeralContainerCommon `json:",inline"`
+
+ // If set, the name of the container from PodSpec that this ephemeral container targets.
+ // The ephemeral container will be run in the namespaces (IPC, PID, etc) of this container.
+ // If not set then the ephemeral container is run in whatever namespaces are shared
+ // for the pod. Note that the container runtime must support this feature.
+ // +optional
+ TargetContainerName string `json:"targetContainerName,omitempty"`
+}
+
+// PodStatus represents information about the status of a pod. Status may trail the actual
+// state of a system, especially if the node that hosts the pod cannot contact the control
+// plane.
+type PodStatus struct {
+ // 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
+ // +optional
+ Phase PodPhase `json:"phase,omitempty"`
+ // Current service state of pod.
+ // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions
+ // +optional
+ // +patchMergeKey=type
+ // +patchStrategy=merge
+ Conditions []PodCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
+ // A human readable message indicating details about why the pod is in this condition.
+ // +optional
+ Message string `json:"message,omitempty"`
+ // A brief CamelCase message indicating details about why the pod is in this state.
+ // e.g. 'Evicted'
+ // +optional
+ Reason string `json:"reason,omitempty"`
+ // 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.
+ // +optional
+ NominatedNodeName string `json:"nominatedNodeName,omitempty"`
+
+ // IP address of the host to which the pod is assigned. Empty if not yet scheduled.
+ // +optional
+ HostIP string `json:"hostIP,omitempty"`
+ // IP address allocated to the pod. Routable at least within the cluster.
+ // Empty if not yet allocated.
+ // +optional
+ PodIP string `json:"podIP,omitempty"`
+
+ // podIPs holds the IP addresses allocated to the pod. If this field is specified, the 0th entry must
+ // match the podIP field. Pods may be allocated at most 1 value for each of IPv4 and IPv6. This list
+ // is empty if no IPs have been allocated yet.
+ // +optional
+ // +patchStrategy=merge
+ // +patchMergeKey=ip
+ PodIPs []PodIP `json:"podIPs,omitempty"`
+
+ // 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.
+ // +optional
+ StartTime *metav1.Time `json:"startTime,omitempty"`
+
+ // The list has one entry per init container in the manifest. The most recent successful
+ // init container will have ready = true, the most recently started container will have
+ // startTime set.
+ // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status
+ InitContainerStatuses []ContainerStatus `json:"initContainerStatuses,omitempty"`
+
+ // The list has one entry per container in the manifest. Each entry is currently the output
+ // of `docker inspect`.
+ // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status
+ // +optional
+ ContainerStatuses []ContainerStatus `json:"containerStatuses,omitempty"`
+ // The Quality of Service (QOS) classification assigned to the pod based on resource requirements
+ // See PodQOSClass type for available QOS classes
+ // More info: https://git.k8s.io/community/contributors/design-proposals/node/resource-qos.md
+ // +optional
+ QOSClass PodQOSClass `json:"qosClass,omitempty"`
+ // Status for any ephemeral containers that have run in this pod.
+ // This field is alpha-level and is only populated by servers that enable the EphemeralContainers feature.
+ // +optional
+ EphemeralContainerStatuses []ContainerStatus `json:"ephemeralContainerStatuses,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PodStatusResult is a wrapper for PodStatus returned by kubelet that can be encode/decoded
+type PodStatusResult struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+ // Most recently observed status of the pod.
+ // This data may not be up to date.
+ // Populated by the system.
+ // Read-only.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Status PodStatus `json:"status,omitempty"`
+}
+
+// +genclient
+// +genclient:method=UpdateEphemeralContainers,verb=update,subresource=ephemeralcontainers
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// Pod is a collection of containers that can run on a host. This resource is created
+// by clients and scheduled onto hosts.
+type Pod struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Specification of the desired behavior of the pod.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Spec PodSpec `json:"spec,omitempty"`
+
+ // Most recently observed status of the pod.
+ // This data may not be up to date.
+ // Populated by the system.
+ // Read-only.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Status PodStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PodList is a list of Pods.
+type PodList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // List of pods.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md
+ Items []Pod `json:"items"`
+}
+
+// PodTemplateSpec describes the data a pod should have when created from a template
+type PodTemplateSpec struct {
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Specification of the desired behavior of the pod.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Spec PodSpec `json:"spec,omitempty"`
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PodTemplate describes a template for creating copies of a predefined pod.
+type PodTemplate struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Template defines the pods that will be created from this pod template.
+ // https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Template PodTemplateSpec `json:"template,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PodTemplateList is a list of PodTemplates.
+type PodTemplateList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // List of pod templates
+ Items []PodTemplate `json:"items"`
+}
+
+// ReplicationControllerSpec is the specification of a replication controller.
+type ReplicationControllerSpec struct {
+ // Replicas is the number of desired replicas.
+ // This is a pointer to distinguish between explicit zero and unspecified.
+ // Defaults to 1.
+ // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#what-is-a-replicationcontroller
+ // +optional
+ Replicas *int32 `json:"replicas,omitempty"`
+
+ // Minimum number of seconds for which a newly created pod should be ready
+ // without any of its container crashing, for it to be considered available.
+ // Defaults to 0 (pod will be considered available as soon as it is ready)
+ // +optional
+ MinReadySeconds int32 `json:"minReadySeconds,omitempty"`
+
+ // Selector is a label query over pods that should match the Replicas count.
+ // If Selector is empty, it is defaulted to the labels present on the Pod template.
+ // Label keys and values that must match in order to be controlled by this replication
+ // controller, if empty defaulted to labels on Pod template.
+ // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
+ // +optional
+ // +mapType=atomic
+ Selector map[string]string `json:"selector,omitempty"`
+
+ // TemplateRef is a reference to an object that describes the pod that will be created if
+ // insufficient replicas are detected.
+ // Reference to an object that describes the pod that will be created if insufficient replicas are detected.
+ // +optional
+ // TemplateRef *ObjectReference `json:"templateRef,omitempty"`
+
+ // Template is the object that describes the pod that will be created if
+ // insufficient replicas are detected. This takes precedence over a TemplateRef.
+ // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template
+ // +optional
+ Template *PodTemplateSpec `json:"template,omitempty"`
+}
+
+// ReplicationControllerStatus represents the current status of a replication
+// controller.
+type ReplicationControllerStatus struct {
+ // Replicas is the most recently oberved number of replicas.
+ // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#what-is-a-replicationcontroller
+ Replicas int32 `json:"replicas"`
+
+ // The number of pods that have labels matching the labels of the pod template of the replication controller.
+ // +optional
+ FullyLabeledReplicas int32 `json:"fullyLabeledReplicas,omitempty"`
+
+ // The number of ready replicas for this replication controller.
+ // +optional
+ ReadyReplicas int32 `json:"readyReplicas,omitempty"`
+
+ // The number of available replicas (ready for at least minReadySeconds) for this replication controller.
+ // +optional
+ AvailableReplicas int32 `json:"availableReplicas,omitempty"`
+
+ // ObservedGeneration reflects the generation of the most recently observed replication controller.
+ // +optional
+ ObservedGeneration int64 `json:"observedGeneration,omitempty"`
+
+ // Represents the latest available observations of a replication controller's current state.
+ // +optional
+ // +patchMergeKey=type
+ // +patchStrategy=merge
+ Conditions []ReplicationControllerCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
+}
+
+type ReplicationControllerConditionType string
+
+// These are valid conditions of a replication controller.
+const (
+ // ReplicationControllerReplicaFailure is added in a replication controller when one of its pods
+ // fails to be created due to insufficient quota, limit ranges, pod security policy, node selectors,
+ // etc. or deleted due to kubelet being down or finalizers are failing.
+ ReplicationControllerReplicaFailure ReplicationControllerConditionType = "ReplicaFailure"
+)
+
+// ReplicationControllerCondition describes the state of a replication controller at a certain point.
+type ReplicationControllerCondition struct {
+ // Type of replication controller condition.
+ Type ReplicationControllerConditionType `json:"type"`
+ // Status of the condition, one of True, False, Unknown.
+ Status ConditionStatus `json:"status"`
+ // The last time the condition transitioned from one status to another.
+ // +optional
+ LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
+ // The reason for the condition's last transition.
+ // +optional
+ Reason string `json:"reason,omitempty"`
+ // A human readable message indicating details about the transition.
+ // +optional
+ Message string `json:"message,omitempty"`
+}
+
+// +genclient
+// +genclient:method=GetScale,verb=get,subresource=scale,result=k8s.io/api/autoscaling/v1.Scale
+// +genclient:method=UpdateScale,verb=update,subresource=scale,input=k8s.io/api/autoscaling/v1.Scale,result=k8s.io/api/autoscaling/v1.Scale
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ReplicationController represents the configuration of a replication controller.
+type ReplicationController struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // If the Labels of a ReplicationController are empty, they are defaulted to
+ // be the same as the Pod(s) that the replication controller manages.
+ // Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Spec defines the specification of the desired behavior of the replication controller.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Spec ReplicationControllerSpec `json:"spec,omitempty"`
+
+ // Status is the most recently observed status of the replication controller.
+ // This data may be out of date by some window of time.
+ // Populated by the system.
+ // Read-only.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Status ReplicationControllerStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ReplicationControllerList is a collection of replication controllers.
+type ReplicationControllerList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // List of replication controllers.
+ // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller
+ Items []ReplicationController `json:"items"`
+}
+
+// Session Affinity Type string
+type ServiceAffinity string
+
+const (
+ // ServiceAffinityClientIP is the Client IP based.
+ ServiceAffinityClientIP ServiceAffinity = "ClientIP"
+
+ // ServiceAffinityNone - no session affinity.
+ ServiceAffinityNone ServiceAffinity = "None"
+)
+
+const DefaultClientIPServiceAffinitySeconds int32 = 10800
+
+// SessionAffinityConfig represents the configurations of session affinity.
+type SessionAffinityConfig struct {
+ // clientIP contains the configurations of Client IP based session affinity.
+ // +optional
+ ClientIP *ClientIPConfig `json:"clientIP,omitempty"`
+}
+
+// ClientIPConfig represents the configurations of Client IP based session affinity.
+type ClientIPConfig struct {
+ // timeoutSeconds specifies the seconds of ClientIP type session sticky time.
+ // The value must be >0 && <=86400(for 1 day) if ServiceAffinity == "ClientIP".
+ // Default value is 10800(for 3 hours).
+ // +optional
+ TimeoutSeconds *int32 `json:"timeoutSeconds,omitempty"`
+}
+
+// Service Type string describes ingress methods for a service
+type ServiceType string
+
+const (
+ // ServiceTypeClusterIP means a service will only be accessible inside the
+ // cluster, via the cluster IP.
+ ServiceTypeClusterIP ServiceType = "ClusterIP"
+
+ // ServiceTypeNodePort means a service will be exposed on one port of
+ // every node, in addition to 'ClusterIP' type.
+ ServiceTypeNodePort ServiceType = "NodePort"
+
+ // ServiceTypeLoadBalancer means a service will be exposed via an
+ // external load balancer (if the cloud provider supports it), in addition
+ // to 'NodePort' type.
+ ServiceTypeLoadBalancer ServiceType = "LoadBalancer"
+
+ // ServiceTypeExternalName means a service consists of only a reference to
+ // an external name that kubedns or equivalent will return as a CNAME
+ // record, with no exposing or proxying of any pods involved.
+ ServiceTypeExternalName ServiceType = "ExternalName"
+)
+
+// ServiceInternalTrafficPolicyType describes the type of traffic routing for
+// internal traffic
+type ServiceInternalTrafficPolicyType string
+
+const (
+ // ServiceInternalTrafficPolicyCluster routes traffic to all endpoints
+ ServiceInternalTrafficPolicyCluster ServiceInternalTrafficPolicyType = "Cluster"
+
+ // ServiceInternalTrafficPolicyLocal only routes to node-local
+ // endpoints, otherwise drops the traffic
+ ServiceInternalTrafficPolicyLocal ServiceInternalTrafficPolicyType = "Local"
+)
+
+// Service External Traffic Policy Type string
+type ServiceExternalTrafficPolicyType string
+
+const (
+ // ServiceExternalTrafficPolicyTypeLocal specifies node-local endpoints behavior.
+ ServiceExternalTrafficPolicyTypeLocal ServiceExternalTrafficPolicyType = "Local"
+ // ServiceExternalTrafficPolicyTypeCluster specifies node-global (legacy) behavior.
+ ServiceExternalTrafficPolicyTypeCluster ServiceExternalTrafficPolicyType = "Cluster"
+)
+
+// These are the valid conditions of a service.
+const (
+ // LoadBalancerPortsError represents the condition of the requested ports
+ // on the cloud load balancer instance.
+ LoadBalancerPortsError = "LoadBalancerPortsError"
+)
+
+// ServiceStatus represents the current status of a service.
+type ServiceStatus struct {
+ // LoadBalancer contains the current status of the load-balancer,
+ // if one is present.
+ // +optional
+ LoadBalancer LoadBalancerStatus `json:"loadBalancer,omitempty"`
+ // Current service state
+ // +optional
+ // +patchMergeKey=type
+ // +patchStrategy=merge
+ // +listType=map
+ // +listMapKey=type
+ Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
+}
+
+// LoadBalancerStatus represents the status of a load-balancer.
+type LoadBalancerStatus struct {
+ // Ingress is a list containing ingress points for the load-balancer.
+ // Traffic intended for the service should be sent to these ingress points.
+ // +optional
+ Ingress []LoadBalancerIngress `json:"ingress,omitempty"`
+}
+
+// LoadBalancerIngress represents the status of a load-balancer ingress point:
+// traffic intended for the service should be sent to an ingress point.
+type LoadBalancerIngress struct {
+ // IP is set for load-balancer ingress points that are IP based
+ // (typically GCE or OpenStack load-balancers)
+ // +optional
+ IP string `json:"ip,omitempty"`
+
+ // Hostname is set for load-balancer ingress points that are DNS based
+ // (typically AWS load-balancers)
+ // +optional
+ Hostname string `json:"hostname,omitempty"`
+
+ // Ports is a list of records of service ports
+ // If used, every port defined in the service should have an entry in it
+ // +listType=atomic
+ // +optional
+ Ports []PortStatus `json:"ports,omitempty"`
+}
+
+// IPFamily represents the IP Family (IPv4 or IPv6). This type is used
+// to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies).
+type IPFamily string
+
+const (
+ // IPv4Protocol indicates that this IP is IPv4 protocol
+ IPv4Protocol IPFamily = "IPv4"
+ // IPv6Protocol indicates that this IP is IPv6 protocol
+ IPv6Protocol IPFamily = "IPv6"
+)
+
+// IPFamilyPolicyType represents the dual-stack-ness requested or required by a Service
+type IPFamilyPolicyType string
+
+const (
+ // IPFamilyPolicySingleStack indicates that this service is required to have a single IPFamily.
+ // The IPFamily assigned is based on the default IPFamily used by the cluster
+ // or as identified by service.spec.ipFamilies field
+ IPFamilyPolicySingleStack IPFamilyPolicyType = "SingleStack"
+ // IPFamilyPolicyPreferDualStack indicates that this service prefers dual-stack when
+ // the cluster is configured for dual-stack. If the cluster is not configured
+ // for dual-stack the service will be assigned a single IPFamily. If the IPFamily is not
+ // set in service.spec.ipFamilies then the service will be assigned the default IPFamily
+ // configured on the cluster
+ IPFamilyPolicyPreferDualStack IPFamilyPolicyType = "PreferDualStack"
+ // IPFamilyPolicyRequireDualStack indicates that this service requires dual-stack. Using
+ // IPFamilyPolicyRequireDualStack on a single stack cluster will result in validation errors. The
+ // IPFamilies (and their order) assigned to this service is based on service.spec.ipFamilies. If
+ // service.spec.ipFamilies was not provided then it will be assigned according to how they are
+ // configured on the cluster. If service.spec.ipFamilies has only one entry then the alternative
+ // IPFamily will be added by apiserver
+ IPFamilyPolicyRequireDualStack IPFamilyPolicyType = "RequireDualStack"
+)
+
+// ServiceSpec describes the attributes that a user creates on a service.
+type ServiceSpec struct {
+ // The list of ports that are exposed by this service.
+ // More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
+ // +patchMergeKey=port
+ // +patchStrategy=merge
+ // +listType=map
+ // +listMapKey=port
+ // +listMapKey=protocol
+ Ports []ServicePort `json:"ports,omitempty" patchStrategy:"merge" patchMergeKey:"port"`
+
+ // Route service traffic to pods with label keys and values matching this
+ // selector. If empty or not present, the service is assumed to have an
+ // external process managing its endpoints, which Kubernetes will not
+ // modify. Only applies to types ClusterIP, NodePort, and LoadBalancer.
+ // Ignored if type is ExternalName.
+ // More info: https://kubernetes.io/docs/concepts/services-networking/service/
+ // +optional
+ // +mapType=atomic
+ Selector map[string]string `json:"selector,omitempty"`
+
+ // clusterIP is the IP address of the service and is usually assigned
+ // randomly. If an address is specified manually, is in-range (as per
+ // system configuration), and is not in use, it will be allocated to the
+ // service; otherwise creation of the service will fail. This field may not
+ // be changed through updates unless the type field is also being changed
+ // to ExternalName (which requires this field to be blank) or the type
+ // field is being changed from ExternalName (in which case this field may
+ // optionally be specified, as describe above). Valid values are "None",
+ // empty string (""), or a valid IP address. Setting this to "None" makes a
+ // "headless service" (no virtual IP), which is useful when direct endpoint
+ // connections are preferred and proxying is not required. Only applies to
+ // types ClusterIP, NodePort, and LoadBalancer. If this field is specified
+ // when creating a Service of type ExternalName, creation will fail. This
+ // field will be wiped when updating a Service to type ExternalName.
+ // More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
+ // +optional
+ ClusterIP string `json:"clusterIP,omitempty"`
+
+ // ClusterIPs is a list of IP addresses assigned to this service, and are
+ // usually assigned randomly. If an address is specified manually, is
+ // in-range (as per system configuration), and is not in use, it will be
+ // allocated to the service; otherwise creation of the service will fail.
+ // This field may not be changed through updates unless the type field is
+ // also being changed to ExternalName (which requires this field to be
+ // empty) or the type field is being changed from ExternalName (in which
+ // case this field may optionally be specified, as describe above). Valid
+ // values are "None", empty string (""), or a valid IP address. Setting
+ // this to "None" makes a "headless service" (no virtual IP), which is
+ // useful when direct endpoint connections are preferred and proxying is
+ // not required. Only applies to types ClusterIP, NodePort, and
+ // LoadBalancer. If this field is specified when creating a Service of type
+ // ExternalName, creation will fail. This field will be wiped when updating
+ // a Service to type ExternalName. If this field is not specified, it will
+ // be initialized from the clusterIP field. If this field is specified,
+ // clients must ensure that clusterIPs[0] and clusterIP have the same
+ // value.
+ //
+ // Unless the "IPv6DualStack" feature gate is enabled, this field is
+ // limited to one value, which must be the same as the clusterIP field. If
+ // the feature gate is enabled, this field may hold a maximum of two
+ // entries (dual-stack IPs, in either order). These IPs must correspond to
+ // the values of the ipFamilies field. Both clusterIPs and ipFamilies are
+ // governed by the ipFamilyPolicy field.
+ // More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
+ // +listType=atomic
+ // +optional
+ ClusterIPs []string `json:"clusterIPs,omitempty"`
+
+ // type determines how the Service is exposed. Defaults to ClusterIP. Valid
+ // options are ExternalName, ClusterIP, NodePort, and LoadBalancer.
+ // "ClusterIP" allocates a cluster-internal IP address for load-balancing
+ // to endpoints. Endpoints are determined by the selector or if that is not
+ // specified, by manual construction of an Endpoints object or
+ // EndpointSlice objects. If clusterIP is "None", no virtual IP is
+ // allocated and the endpoints are published as a set of endpoints rather
+ // than a virtual IP.
+ // "NodePort" builds on ClusterIP and allocates a port on every node which
+ // routes to the same endpoints as the clusterIP.
+ // "LoadBalancer" builds on NodePort and creates an external load-balancer
+ // (if supported in the current cloud) which routes to the same endpoints
+ // as the clusterIP.
+ // "ExternalName" aliases this service to the specified externalName.
+ // Several other fields do not apply to ExternalName services.
+ // More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
+ // +optional
+ Type ServiceType `json:"type,omitempty"`
+
+ // externalIPs is a list of IP addresses for which nodes in the cluster
+ // will also accept traffic for this service. These IPs are not managed by
+ // Kubernetes. The user is responsible for ensuring that traffic arrives
+ // at a node with this IP. A common example is external load-balancers
+ // that are not part of the Kubernetes system.
+ // +optional
+ ExternalIPs []string `json:"externalIPs,omitempty"`
+
+ // Supports "ClientIP" and "None". Used to maintain session affinity.
+ // Enable client IP based session affinity.
+ // Must be ClientIP or None.
+ // Defaults to None.
+ // More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
+ // +optional
+ SessionAffinity ServiceAffinity `json:"sessionAffinity,omitempty"`
+
+ // Only applies to Service Type: LoadBalancer
+ // LoadBalancer will get created with the IP specified in this field.
+ // This feature depends on whether the underlying cloud-provider supports specifying
+ // the loadBalancerIP when a load balancer is created.
+ // This field will be ignored if the cloud-provider does not support the feature.
+ // +optional
+ LoadBalancerIP string `json:"loadBalancerIP,omitempty"`
+
+ // If specified and supported by the platform, this will restrict traffic through the cloud-provider
+ // load-balancer will be restricted to the specified client IPs. This field will be ignored if the
+ // cloud-provider does not support the feature."
+ // More info: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/
+ // +optional
+ LoadBalancerSourceRanges []string `json:"loadBalancerSourceRanges,omitempty"`
+
+ // externalName is the external reference that discovery mechanisms will
+ // return as an alias for this service (e.g. a DNS CNAME record). No
+ // proxying will be involved. Must be a lowercase RFC-1123 hostname
+ // (https://tools.ietf.org/html/rfc1123) and requires `type` to be "ExternalName".
+ // +optional
+ ExternalName string `json:"externalName,omitempty"`
+
+ // externalTrafficPolicy denotes if this Service desires to route external
+ // traffic to node-local or cluster-wide endpoints. "Local" preserves the
+ // client source IP and avoids a second hop for LoadBalancer and Nodeport
+ // type services, but risks potentially imbalanced traffic spreading.
+ // "Cluster" obscures the client source IP and may cause a second hop to
+ // another node, but should have good overall load-spreading.
+ // +optional
+ ExternalTrafficPolicy ServiceExternalTrafficPolicyType `json:"externalTrafficPolicy,omitempty"`
+
+ // healthCheckNodePort specifies the healthcheck nodePort for the service.
+ // This only applies when type is set to LoadBalancer and
+ // externalTrafficPolicy is set to Local. If a value is specified, is
+ // in-range, and is not in use, it will be used. If not specified, a value
+ // will be automatically allocated. External systems (e.g. load-balancers)
+ // can use this port to determine if a given node holds endpoints for this
+ // service or not. If this field is specified when creating a Service
+ // which does not need it, creation will fail. This field will be wiped
+ // when updating a Service to no longer need it (e.g. changing type).
+ // +optional
+ HealthCheckNodePort int32 `json:"healthCheckNodePort,omitempty"`
+
+ // publishNotReadyAddresses indicates that any agent which deals with endpoints for this
+ // Service should disregard any indications of ready/not-ready.
+ // The primary use case for setting this field is for a StatefulSet's Headless Service to
+ // propagate SRV DNS records for its Pods for the purpose of peer discovery.
+ // The Kubernetes controllers that generate Endpoints and EndpointSlice resources for
+ // Services interpret this to mean that all endpoints are considered "ready" even if the
+ // Pods themselves are not. Agents which consume only Kubernetes generated endpoints
+ // through the Endpoints or EndpointSlice resources can safely assume this behavior.
+ // +optional
+ PublishNotReadyAddresses bool `json:"publishNotReadyAddresses,omitempty"`
+
+ // sessionAffinityConfig contains the configurations of session affinity.
+ // +optional
+ SessionAffinityConfig *SessionAffinityConfig `json:"sessionAffinityConfig,omitempty"`
+
+ // TopologyKeys is tombstoned to show why 16 is reserved protobuf tag.
+ //TopologyKeys []string `json:"topologyKeys,omitempty"`
+
+ // IPFamily is tombstoned to show why 15 is a reserved protobuf tag.
+ // IPFamily *IPFamily `json:"ipFamily,omitempty"`
+
+ // IPFamilies is a list of IP families (e.g. IPv4, IPv6) assigned to this
+ // service, and is gated by the "IPv6DualStack" feature gate. This field
+ // is usually assigned automatically based on cluster configuration and the
+ // ipFamilyPolicy field. If this field is specified manually, the requested
+ // family is available in the cluster, and ipFamilyPolicy allows it, it
+ // will be used; otherwise creation of the service will fail. This field
+ // is conditionally mutable: it allows for adding or removing a secondary
+ // IP family, but it does not allow changing the primary IP family of the
+ // Service. Valid values are "IPv4" and "IPv6". This field only applies
+ // to Services of types ClusterIP, NodePort, and LoadBalancer, and does
+ // apply to "headless" services. This field will be wiped when updating a
+ // Service to type ExternalName.
+ //
+ // This field may hold a maximum of two entries (dual-stack families, in
+ // either order). These families must correspond to the values of the
+ // clusterIPs field, if specified. Both clusterIPs and ipFamilies are
+ // governed by the ipFamilyPolicy field.
+ // +listType=atomic
+ // +optional
+ IPFamilies []IPFamily `json:"ipFamilies,omitempty"`
+
+ // IPFamilyPolicy represents the dual-stack-ness requested or required by
+ // this Service, and is gated by the "IPv6DualStack" feature gate. If
+ // there is no value provided, then this field will be set to SingleStack.
+ // Services can be "SingleStack" (a single IP family), "PreferDualStack"
+ // (two IP families on dual-stack configured clusters or a single IP family
+ // on single-stack clusters), or "RequireDualStack" (two IP families on
+ // dual-stack configured clusters, otherwise fail). The ipFamilies and
+ // clusterIPs fields depend on the value of this field. This field will be
+ // wiped when updating a service to type ExternalName.
+ // +optional
+ IPFamilyPolicy *IPFamilyPolicyType `json:"ipFamilyPolicy,omitempty"`
+
+ // allocateLoadBalancerNodePorts defines if NodePorts will be automatically
+ // allocated for services with type LoadBalancer. Default is "true". It
+ // may be set to "false" if the cluster load-balancer does not rely on
+ // NodePorts. If the caller requests specific NodePorts (by specifying a
+ // value), those requests will be respected, regardless of this field.
+ // This field may only be set for services with type LoadBalancer and will
+ // be cleared if the type is changed to any other type.
+ // This field is beta-level and is only honored by servers that enable the ServiceLBNodePortControl feature.
+ // +featureGate=ServiceLBNodePortControl
+ // +optional
+ AllocateLoadBalancerNodePorts *bool `json:"allocateLoadBalancerNodePorts,omitempty"`
+
+ // loadBalancerClass is the class of the load balancer implementation this Service belongs to.
+ // If specified, the value of this field must be a label-style identifier, with an optional prefix,
+ // e.g. "internal-vip" or "example.com/internal-vip". Unprefixed names are reserved for end-users.
+ // This field can only be set when the Service type is 'LoadBalancer'. If not set, the default load
+ // balancer implementation is used, today this is typically done through the cloud provider integration,
+ // but should apply for any default implementation. If set, it is assumed that a load balancer
+ // implementation is watching for Services with a matching class. Any default load balancer
+ // implementation (e.g. cloud providers) should ignore Services that set this field.
+ // This field can only be set when creating or updating a Service to type 'LoadBalancer'.
+ // Once set, it can not be changed. This field will be wiped when a service is updated to a non 'LoadBalancer' type.
+ // +featureGate=LoadBalancerClass
+ // +optional
+ LoadBalancerClass *string `json:"loadBalancerClass,omitempty"`
+
+ // InternalTrafficPolicy specifies if the cluster internal traffic
+ // should be routed to all endpoints or node-local endpoints only.
+ // "Cluster" routes internal traffic to a Service to all endpoints.
+ // "Local" routes traffic to node-local endpoints only, traffic is
+ // dropped if no node-local endpoints are ready.
+ // The default value is "Cluster".
+ // +featureGate=ServiceInternalTrafficPolicy
+ // +optional
+ InternalTrafficPolicy *ServiceInternalTrafficPolicyType `json:"internalTrafficPolicy,omitempty"`
+}
+
+// ServicePort contains information on service's port.
+type ServicePort struct {
+ // The name of this port within the service. This must be a DNS_LABEL.
+ // All ports within a ServiceSpec must have unique names. When considering
+ // the endpoints for a Service, this must match the 'name' field in the
+ // EndpointPort.
+ // Optional if only one ServicePort is defined on this service.
+ // +optional
+ Name string `json:"name,omitempty"`
+
+ // The IP protocol for this port. Supports "TCP", "UDP", and "SCTP".
+ // Default is TCP.
+ // +default="TCP"
+ // +optional
+ Protocol Protocol `json:"protocol,omitempty"`
+
+ // The application protocol for this port.
+ // This field follows standard Kubernetes label syntax.
+ // Un-prefixed names are reserved for IANA standard service names (as per
+ // RFC-6335 and http://www.iana.org/assignments/service-names).
+ // Non-standard protocols should use prefixed names such as
+ // mycompany.com/my-custom-protocol.
+ // +optional
+ AppProtocol *string `json:"appProtocol,omitempty"`
+
+ // The port that will be exposed by this service.
+ Port int32 `json:"port"`
+
+ // Number or name of the port to access on the pods targeted by the service.
+ // Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME.
+ // If this is a string, it will be looked up as a named port in the
+ // target Pod's container ports. If this is not specified, the value
+ // of the 'port' field is used (an identity map).
+ // This field is ignored for services with clusterIP=None, and should be
+ // omitted or set equal to the 'port' field.
+ // More info: https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service
+ // +optional
+ TargetPort intstr.IntOrString `json:"targetPort,omitempty"`
+
+ // The port on each node on which this service is exposed when type is
+ // NodePort or LoadBalancer. Usually assigned by the system. If a value is
+ // specified, in-range, and not in use it will be used, otherwise the
+ // operation will fail. If not specified, a port will be allocated if this
+ // Service requires one. If this field is specified when creating a
+ // Service which does not need it, creation will fail. This field will be
+ // wiped when updating a Service to no longer need it (e.g. changing type
+ // from NodePort to ClusterIP).
+ // More info: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport
+ // +optional
+ NodePort int32 `json:"nodePort,omitempty"`
+}
+
+// +genclient
+// +genclient:skipVerbs=deleteCollection
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// Service is a named abstraction of software service (for example, mysql) consisting of local port
+// (for example 3306) that the proxy listens on, and the selector that determines which pods
+// will answer requests sent through the proxy.
+type Service struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Spec defines the behavior of a service.
+ // https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Spec ServiceSpec `json:"spec,omitempty"`
+
+ // Most recently observed status of the service.
+ // Populated by the system.
+ // Read-only.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Status ServiceStatus `json:"status,omitempty"`
+}
+
+const (
+ // ClusterIPNone - do not assign a cluster IP
+ // no proxying required and no environment variables should be created for pods
+ ClusterIPNone = "None"
+)
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ServiceList holds a list of services.
+type ServiceList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // List of services
+ Items []Service `json:"items"`
+}
+
+// +genclient
+// +genclient:method=CreateToken,verb=create,subresource=token,input=k8s.io/api/authentication/v1.TokenRequest,result=k8s.io/api/authentication/v1.TokenRequest
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ServiceAccount binds together:
+// * a name, understood by users, and perhaps by peripheral systems, for an identity
+// * a principal that can be authenticated and authorized
+// * a set of secrets
+type ServiceAccount struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount.
+ // More info: https://kubernetes.io/docs/concepts/configuration/secret
+ // +optional
+ // +patchMergeKey=name
+ // +patchStrategy=merge
+ Secrets []ObjectReference `json:"secrets,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
+
+ // ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images
+ // in pods that reference this ServiceAccount. ImagePullSecrets are distinct from Secrets because Secrets
+ // can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet.
+ // More info: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
+ // +optional
+ ImagePullSecrets []LocalObjectReference `json:"imagePullSecrets,omitempty"`
+
+ // AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted.
+ // Can be overridden at the pod level.
+ // +optional
+ AutomountServiceAccountToken *bool `json:"automountServiceAccountToken,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ServiceAccountList is a list of ServiceAccount objects
+type ServiceAccountList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // List of ServiceAccounts.
+ // More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
+ Items []ServiceAccount `json:"items"`
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// Endpoints is a collection of endpoints that implement the actual service. Example:
+// Name: "mysvc",
+// Subsets: [
+// {
+// Addresses: [{"ip": "10.10.1.1"}, {"ip": "10.10.2.2"}],
+// Ports: [{"name": "a", "port": 8675}, {"name": "b", "port": 309}]
+// },
+// {
+// Addresses: [{"ip": "10.10.3.3"}],
+// Ports: [{"name": "a", "port": 93}, {"name": "b", "port": 76}]
+// },
+// ]
+type Endpoints struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // The set of all endpoints is the union of all subsets. Addresses are placed into
+ // subsets according to the IPs they share. A single address with multiple ports,
+ // some of which are ready and some of which are not (because they come from
+ // different containers) will result in the address being displayed in different
+ // subsets for the different ports. No address will appear in both Addresses and
+ // NotReadyAddresses in the same subset.
+ // Sets of addresses and ports that comprise a service.
+ // +optional
+ Subsets []EndpointSubset `json:"subsets,omitempty"`
+}
+
+// EndpointSubset is a group of addresses with a common set of ports. The
+// expanded set of endpoints is the Cartesian product of Addresses x Ports.
+// For example, given:
+// {
+// Addresses: [{"ip": "10.10.1.1"}, {"ip": "10.10.2.2"}],
+// Ports: [{"name": "a", "port": 8675}, {"name": "b", "port": 309}]
+// }
+// The resulting set of endpoints can be viewed as:
+// a: [ 10.10.1.1:8675, 10.10.2.2:8675 ],
+// b: [ 10.10.1.1:309, 10.10.2.2:309 ]
+type EndpointSubset struct {
+ // IP addresses which offer the related ports that are marked as ready. These endpoints
+ // should be considered safe for load balancers and clients to utilize.
+ // +optional
+ Addresses []EndpointAddress `json:"addresses,omitempty"`
+ // IP addresses which offer the related ports but are not currently marked as ready
+ // because they have not yet finished starting, have recently failed a readiness check,
+ // or have recently failed a liveness check.
+ // +optional
+ NotReadyAddresses []EndpointAddress `json:"notReadyAddresses,omitempty"`
+ // Port numbers available on the related IP addresses.
+ // +optional
+ Ports []EndpointPort `json:"ports,omitempty"`
+}
+
+// EndpointAddress is a tuple that describes single IP address.
+// +structType=atomic
+type EndpointAddress struct {
+ // The IP of this endpoint.
+ // May not be loopback (127.0.0.0/8), link-local (169.254.0.0/16),
+ // or link-local multicast ((224.0.0.0/24).
+ // IPv6 is also accepted but not fully supported on all platforms. Also, certain
+ // kubernetes components, like kube-proxy, are not IPv6 ready.
+ // TODO: This should allow hostname or IP, See #4447.
+ IP string `json:"ip"`
+ // The Hostname of this endpoint
+ // +optional
+ Hostname string `json:"hostname,omitempty"`
+ // Optional: Node hosting this endpoint. This can be used to determine endpoints local to a node.
+ // +optional
+ NodeName *string `json:"nodeName,omitempty"`
+ // Reference to object providing the endpoint.
+ // +optional
+ TargetRef *ObjectReference `json:"targetRef,omitempty"`
+}
+
+// EndpointPort is a tuple that describes a single port.
+// +structType=atomic
+type EndpointPort struct {
+ // The name of this port. This must match the 'name' field in the
+ // corresponding ServicePort.
+ // Must be a DNS_LABEL.
+ // Optional only if one port is defined.
+ // +optional
+ Name string `json:"name,omitempty"`
+
+ // The port number of the endpoint.
+ Port int32 `json:"port"`
+
+ // The IP protocol for this port.
+ // Must be UDP, TCP, or SCTP.
+ // Default is TCP.
+ // +optional
+ Protocol Protocol `json:"protocol,omitempty"`
+
+ // The application protocol for this port.
+ // This field follows standard Kubernetes label syntax.
+ // Un-prefixed names are reserved for IANA standard service names (as per
+ // RFC-6335 and http://www.iana.org/assignments/service-names).
+ // Non-standard protocols should use prefixed names such as
+ // mycompany.com/my-custom-protocol.
+ // +optional
+ AppProtocol *string `json:"appProtocol,omitempty"`
+}
+
+// ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node.
+// This API is deprecated since 1.22: https://git.k8s.io/enhancements/keps/sig-node/281-dynamic-kubelet-configuration
+type ConfigMapNodeConfigSource struct {
+ // Namespace is the metadata.namespace of the referenced ConfigMap.
+ // This field is required in all cases.
+ Namespace string `json:"namespace"`
+
+ // Name is the metadata.name of the referenced ConfigMap.
+ // This field is required in all cases.
+ Name string `json:"name"`
+
+ // UID is the metadata.UID of the referenced ConfigMap.
+ // This field is forbidden in Node.Spec, and required in Node.Status.
+ // +optional
+ UID types.UID `json:"uid,omitempty"`
+
+ // ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap.
+ // This field is forbidden in Node.Spec, and required in Node.Status.
+ // +optional
+ ResourceVersion string `json:"resourceVersion,omitempty"`
+
+ // KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure
+ // This field is required in all cases.
+ KubeletConfigKey string `json:"kubeletConfigKey"`
+}
+
+// Describe a container image
+type ContainerImage struct {
+ // Names by which this image is known.
+ // e.g. ["k8s.gcr.io/hyperkube:v1.0.7", "dockerhub.io/google_containers/hyperkube:v1.0.7"]
+ // +optional
+ Names []string `json:"names"`
+ // The size of the image in bytes.
+ // +optional
+ SizeBytes int64 `json:"sizeBytes,omitempty"`
+}
+
+// ResourceName is the name identifying various resources in a ResourceList.
+type ResourceName string
+
+// Resource names must be not more than 63 characters, consisting of upper- or lower-case alphanumeric characters,
+// with the -, _, and . characters allowed anywhere, except the first or last character.
+// The default convention, matching that for annotations, is to use lower-case names, with dashes, rather than
+// camel case, separating compound words.
+// Fully-qualified resource typenames are constructed from a DNS-style subdomain, followed by a slash `/` and a name.
+const (
+ // CPU, in cores. (500m = .5 cores)
+ ResourceCPU ResourceName = "cpu"
+ // Memory, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
+ ResourceMemory ResourceName = "memory"
+ // Volume size, in bytes (e,g. 5Gi = 5GiB = 5 * 1024 * 1024 * 1024)
+ ResourceStorage ResourceName = "storage"
+ // Local ephemeral storage, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
+ // The resource name for ResourceEphemeralStorage is alpha and it can change across releases.
+ ResourceEphemeralStorage ResourceName = "ephemeral-storage"
+)
+
+const (
+ // Default namespace prefix.
+ ResourceDefaultNamespacePrefix = "kubernetes.io/"
+ // Name prefix for huge page resources (alpha).
+ ResourceHugePagesPrefix = "hugepages-"
+ // Name prefix for storage resource limits
+ ResourceAttachableVolumesPrefix = "attachable-volumes-"
+)
+
+// ResourceList is a set of (resource name, quantity) pairs.
+type ResourceList map[ResourceName]resource.Quantity
+
+// PodLogOptions is the query options for a Pod's logs REST call.
+type PodLogOptions struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // The container for which to stream logs. Defaults to only container if there is one container in the pod.
+ // +optional
+ Container string `json:"container,omitempty"`
+ // Follow the log stream of the pod. Defaults to false.
+ // +optional
+ Follow bool `json:"follow,omitempty"`
+ // Return previous terminated container logs. Defaults to false.
+ // +optional
+ Previous bool `json:"previous,omitempty"`
+ // A relative time in seconds before the current time from which to show logs. If this value
+ // precedes the time a pod was started, only logs since the pod start will be returned.
+ // If this value is in the future, no logs will be returned.
+ // Only one of sinceSeconds or sinceTime may be specified.
+ // +optional
+ SinceSeconds *int64 `json:"sinceSeconds,omitempty"`
+ // An RFC3339 timestamp from which to show logs. If this value
+ // precedes the time a pod was started, only logs since the pod start will be returned.
+ // If this value is in the future, no logs will be returned.
+ // Only one of sinceSeconds or sinceTime may be specified.
+ // +optional
+ SinceTime *metav1.Time `json:"sinceTime,omitempty"`
+ // If true, add an RFC3339 or RFC3339Nano timestamp at the beginning of every line
+ // of log output. Defaults to false.
+ // +optional
+ Timestamps bool `json:"timestamps,omitempty"`
+ // If set, the number of lines from the end of the logs to show. If not specified,
+ // logs are shown from the creation of the container or sinceSeconds or sinceTime
+ // +optional
+ TailLines *int64 `json:"tailLines,omitempty"`
+ // If set, the number of bytes to read from the server before terminating the
+ // log output. This may not display a complete final line of logging, and may return
+ // slightly more or slightly less than the specified limit.
+ // +optional
+ LimitBytes *int64 `json:"limitBytes,omitempty"`
+
+ // insecureSkipTLSVerifyBackend indicates that the apiserver should not confirm the validity of the
+ // serving certificate of the backend it is connecting to. This will make the HTTPS connection between the apiserver
+ // and the backend insecure. This means the apiserver cannot verify the log data it is receiving came from the real
+ // kubelet. If the kubelet is configured to verify the apiserver's TLS credentials, it does not mean the
+ // connection to the real kubelet is vulnerable to a man in the middle attack (e.g. an attacker could not intercept
+ // the actual log data coming from the real kubelet).
+ // +optional
+ InsecureSkipTLSVerifyBackend bool `json:"insecureSkipTLSVerifyBackend,omitempty"`
+}
+
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PodAttachOptions is the query options to a Pod's remote attach call.
+// ---
+// TODO: merge w/ PodExecOptions below for stdin, stdout, etc
+// and also when we cut V2, we should export a "StreamOptions" or somesuch that contains Stdin, Stdout, Stder and TTY
+type PodAttachOptions struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // Stdin if true, redirects the standard input stream of the pod for this call.
+ // Defaults to false.
+ // +optional
+ Stdin bool `json:"stdin,omitempty"`
+
+ // Stdout if true indicates that stdout is to be redirected for the attach call.
+ // Defaults to true.
+ // +optional
+ Stdout bool `json:"stdout,omitempty"`
+
+ // Stderr if true indicates that stderr is to be redirected for the attach call.
+ // Defaults to true.
+ // +optional
+ Stderr bool `json:"stderr,omitempty"`
+
+ // TTY if true indicates that a tty will be allocated for the attach call.
+ // This is passed through the container runtime so the tty
+ // is allocated on the worker node by the container runtime.
+ // Defaults to false.
+ // +optional
+ TTY bool `json:"tty,omitempty"`
+
+ // The container in which to execute the command.
+ // Defaults to only container if there is only one container in the pod.
+ // +optional
+ Container string `json:"container,omitempty"`
+}
+
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PodExecOptions is the query options to a Pod's remote exec call.
+// ---
+// TODO: This is largely identical to PodAttachOptions above, make sure they stay in sync and see about merging
+// and also when we cut V2, we should export a "StreamOptions" or somesuch that contains Stdin, Stdout, Stder and TTY
+type PodExecOptions struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // Redirect the standard input stream of the pod for this call.
+ // Defaults to false.
+ // +optional
+ Stdin bool `json:"stdin,omitempty"`
+
+ // Redirect the standard output stream of the pod for this call.
+ // Defaults to true.
+ // +optional
+ Stdout bool `json:"stdout,omitempty"`
+
+ // Redirect the standard error stream of the pod for this call.
+ // Defaults to true.
+ // +optional
+ Stderr bool `json:"stderr,omitempty"`
+
+ // TTY if true indicates that a tty will be allocated for the exec call.
+ // Defaults to false.
+ // +optional
+ TTY bool `json:"tty,omitempty"`
+
+ // Container in which to execute the command.
+ // Defaults to only container if there is only one container in the pod.
+ // +optional
+ Container string `json:"container,omitempty"`
+
+ // Command is the remote command to execute. argv array. Not executed within a shell.
+ Command []string `json:"command"`
+}
+
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PodPortForwardOptions is the query options to a Pod's port forward call
+// when using WebSockets.
+// The `port` query parameter must specify the port or
+// ports (comma separated) to forward over.
+// Port forwarding over SPDY does not use these options. It requires the port
+// to be passed in the `port` header as part of request.
+type PodPortForwardOptions struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // List of ports to forward
+ // Required when using WebSockets
+ // +optional
+ Ports []int32 `json:"ports,omitempty"`
+}
+
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PodProxyOptions is the query options to a Pod's proxy call.
+type PodProxyOptions struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // Path is the URL path to use for the current proxy request to pod.
+ // +optional
+ Path string `json:"path,omitempty"`
+}
+
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// NodeProxyOptions is the query options to a Node's proxy call.
+type NodeProxyOptions struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // Path is the URL path to use for the current proxy request to node.
+ // +optional
+ Path string `json:"path,omitempty"`
+}
+
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ServiceProxyOptions is the query options to a Service's proxy call.
+type ServiceProxyOptions struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // Path is the part of URLs that include service endpoints, suffixes,
+ // and parameters to use for the current proxy request to service.
+ // For example, the whole request URL is
+ // http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy.
+ // Path is _search?q=user:kimchy.
+ // +optional
+ Path string `json:"path,omitempty"`
+}
+
+// ObjectReference contains enough information to let you inspect or modify the referred object.
+// ---
+// New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs.
+// 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage.
+// 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular
+// restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted".
+// Those cannot be well described when embedded.
+// 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen.
+// 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity
+// during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple
+// and the version of the actual struct is irrelevant.
+// 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type
+// will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control.
+// Instead of using this type, create a locally provided and used type that is well-focused on your reference.
+// For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 .
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +structType=atomic
+type ObjectReference struct {
+ // Kind of the referent.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ Kind string `json:"kind,omitempty"`
+ // Namespace of the referent.
+ // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
+ // +optional
+ Namespace string `json:"namespace,omitempty"`
+ // Name of the referent.
+ // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
+ // +optional
+ Name string `json:"name,omitempty"`
+ // UID of the referent.
+ // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
+ // +optional
+ UID types.UID `json:"uid,omitempty"`
+ // API version of the referent.
+ // +optional
+ APIVersion string `json:"apiVersion,omitempty"`
+ // Specific resourceVersion to which this reference is made, if any.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
+ // +optional
+ ResourceVersion string `json:"resourceVersion,omitempty"`
+
+ // If referring to a piece of an object instead of an entire object, this string
+ // should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
+ // For example, if the object reference is to a container within a pod, this would take on a value like:
+ // "spec.containers{name}" (where "name" refers to the name of the container that triggered
+ // the event) or if no container name is specified "spec.containers[2]" (container with
+ // index 2 in this pod). This syntax is chosen only to have some well-defined way of
+ // referencing a part of an object.
+ // TODO: this design is not final and this field is subject to change in the future.
+ // +optional
+ FieldPath string `json:"fieldPath,omitempty"`
+}
+
+// LocalObjectReference contains enough information to let you locate the
+// referenced object inside the same namespace.
+// +structType=atomic
+type LocalObjectReference struct {
+ // Name of the referent.
+ // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
+ // TODO: Add other useful fields. apiVersion, kind, uid?
+ // +optional
+ Name string `json:"name,omitempty"`
+}
+
+// TypedLocalObjectReference contains enough information to let you locate the
+// typed referenced object inside the same namespace.
+// +structType=atomic
+type TypedLocalObjectReference struct {
+ // APIGroup is the group for the resource being referenced.
+ // If APIGroup is not specified, the specified Kind must be in the core API group.
+ // For any other third-party types, APIGroup is required.
+ // +optional
+ APIGroup *string `json:"apiGroup"`
+ // Kind is the type of resource being referenced
+ Kind string `json:"kind"`
+ // Name is the name of resource being referenced
+ Name string `json:"name"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// SerializedReference is a reference to serialized object.
+type SerializedReference struct {
+ metav1.TypeMeta `json:",inline"`
+ // The reference to an object in the system.
+ // +optional
+ Reference ObjectReference `json:"reference,omitempty"`
+}
+
+// EventSource contains information for an event.
+type EventSource struct {
+ // Component from which the event is generated.
+ // +optional
+ Component string `json:"component,omitempty"`
+ // Node name on which the event is generated.
+ // +optional
+ Host string `json:"host,omitempty"`
+}
+
+// Valid values for event types (new types could be added in future)
+const (
+ // Information only and will not cause any problems
+ EventTypeNormal string = "Normal"
+ // These events are to warn that something might go wrong
+ EventTypeWarning string = "Warning"
+)
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// Event is a report of an event somewhere in the cluster. Events
+// have a limited retention time and triggers and messages may evolve
+// with time. Event consumers should not rely on the timing of an event
+// with a given Reason reflecting a consistent underlying trigger, or the
+// continued existence of events with that Reason. Events should be
+// treated as informative, best-effort, supplemental data.
+type Event struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ metav1.ObjectMeta `json:"metadata"`
+
+ // The object that this event is about.
+ InvolvedObject ObjectReference `json:"involvedObject"`
+
+ // This should be a short, machine understandable string that gives the reason
+ // for the transition into the object's current status.
+ // TODO: provide exact specification for format.
+ // +optional
+ Reason string `json:"reason,omitempty"`
+
+ // A human-readable description of the status of this operation.
+ // TODO: decide on maximum length.
+ // +optional
+ Message string `json:"message,omitempty"`
+
+ // The component reporting this event. Should be a short machine understandable string.
+ // +optional
+ Source EventSource `json:"source,omitempty"`
+
+ // The time at which the event was first recorded. (Time of server receipt is in TypeMeta.)
+ // +optional
+ FirstTimestamp metav1.Time `json:"firstTimestamp,omitempty"`
+
+ // The time at which the most recent occurrence of this event was recorded.
+ // +optional
+ LastTimestamp metav1.Time `json:"lastTimestamp,omitempty"`
+
+ // The number of times this event has occurred.
+ // +optional
+ Count int32 `json:"count,omitempty"`
+
+ // Type of this event (Normal, Warning), new types could be added in the future
+ // +optional
+ Type string `json:"type,omitempty"`
+
+ // Time when this Event was first observed.
+ // +optional
+ EventTime metav1.MicroTime `json:"eventTime,omitempty"`
+
+ // Data about the Event series this event represents or nil if it's a singleton Event.
+ // +optional
+ Series *EventSeries `json:"series,omitempty"`
+
+ // What action was taken/failed regarding to the Regarding object.
+ // +optional
+ Action string `json:"action,omitempty"`
+
+ // Optional secondary object for more complex actions.
+ // +optional
+ Related *ObjectReference `json:"related,omitempty"`
+
+ // Name of the controller that emitted this Event, e.g. `kubernetes.io/kubelet`.
+ // +optional
+ ReportingController string `json:"reportingComponent"`
+
+ // ID of the controller instance, e.g. `kubelet-xyzf`.
+ // +optional
+ ReportingInstance string `json:"reportingInstance"`
+}
+
+// EventSeries contain information on series of events, i.e. thing that was/is happening
+// continuously for some time.
+type EventSeries struct {
+ // Number of occurrences in this series up to the last heartbeat time
+ Count int32 `json:"count,omitempty"`
+ // Time of the last occurrence observed
+ LastObservedTime metav1.MicroTime `json:"lastObservedTime,omitempty"`
+
+ // +k8s:deprecated=state,protobuf=3
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// EventList is a list of events.
+type EventList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // List of events
+ Items []Event `json:"items"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// LimitType is a type of object that is limited
+type LimitType string
+
+const (
+ // Limit that applies to all pods in a namespace
+ LimitTypePod LimitType = "Pod"
+ // Limit that applies to all containers in a namespace
+ LimitTypeContainer LimitType = "Container"
+ // Limit that applies to all persistent volume claims in a namespace
+ LimitTypePersistentVolumeClaim LimitType = "PersistentVolumeClaim"
+)
+
+// LimitRangeItem defines a min/max usage limit for any resource that matches on kind.
+type LimitRangeItem struct {
+ // Type of resource that this limit applies to.
+ Type LimitType `json:"type"`
+ // Max usage constraints on this kind by resource name.
+ // +optional
+ Max ResourceList `json:"max,omitempty"`
+ // Min usage constraints on this kind by resource name.
+ // +optional
+ Min ResourceList `json:"min,omitempty"`
+ // Default resource requirement limit value by resource name if resource limit is omitted.
+ // +optional
+ Default ResourceList `json:"default,omitempty"`
+ // DefaultRequest is the default resource requirement request value by resource name if resource request is omitted.
+ // +optional
+ DefaultRequest ResourceList `json:"defaultRequest,omitempty"`
+ // MaxLimitRequestRatio if specified, the named resource must have a request and limit that are both non-zero where limit divided by request is less than or equal to the enumerated value; this represents the max burst for the named resource.
+ // +optional
+ MaxLimitRequestRatio ResourceList `json:"maxLimitRequestRatio,omitempty"`
+}
+
+// LimitRangeSpec defines a min/max usage limit for resources that match on kind.
+type LimitRangeSpec struct {
+ // Limits is the list of LimitRangeItem objects that are enforced.
+ Limits []LimitRangeItem `json:"limits"`
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// LimitRange sets resource usage limits for each kind of resource in a Namespace.
+type LimitRange struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Spec defines the limits enforced.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Spec LimitRangeSpec `json:"spec,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// LimitRangeList is a list of LimitRange items.
+type LimitRangeList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // Items is a list of LimitRange objects.
+ // More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
+ Items []LimitRange `json:"items"`
+}
+
+// The following identify resource constants for Kubernetes object types
+const (
+ // Pods, number
+ ResourcePods ResourceName = "pods"
+ // Services, number
+ ResourceServices ResourceName = "services"
+ // ReplicationControllers, number
+ ResourceReplicationControllers ResourceName = "replicationcontrollers"
+ // ResourceQuotas, number
+ ResourceQuotas ResourceName = "resourcequotas"
+ // ResourceSecrets, number
+ ResourceSecrets ResourceName = "secrets"
+ // ResourceConfigMaps, number
+ ResourceConfigMaps ResourceName = "configmaps"
+ // ResourcePersistentVolumeClaims, number
+ ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
+ // ResourceServicesNodePorts, number
+ ResourceServicesNodePorts ResourceName = "services.nodeports"
+ // ResourceServicesLoadBalancers, number
+ ResourceServicesLoadBalancers ResourceName = "services.loadbalancers"
+ // CPU request, in cores. (500m = .5 cores)
+ ResourceRequestsCPU ResourceName = "requests.cpu"
+ // Memory request, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
+ ResourceRequestsMemory ResourceName = "requests.memory"
+ // Storage request, in bytes
+ ResourceRequestsStorage ResourceName = "requests.storage"
+ // Local ephemeral storage request, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
+ ResourceRequestsEphemeralStorage ResourceName = "requests.ephemeral-storage"
+ // CPU limit, in cores. (500m = .5 cores)
+ ResourceLimitsCPU ResourceName = "limits.cpu"
+ // Memory limit, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
+ ResourceLimitsMemory ResourceName = "limits.memory"
+ // Local ephemeral storage limit, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
+ ResourceLimitsEphemeralStorage ResourceName = "limits.ephemeral-storage"
+)
+
+// The following identify resource prefix for Kubernetes object types
+const (
+ // HugePages request, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
+ // As burst is not supported for HugePages, we would only quota its request, and ignore the limit.
+ ResourceRequestsHugePagesPrefix = "requests.hugepages-"
+ // Default resource requests prefix
+ DefaultResourceRequestsPrefix = "requests."
+)
+
+// A ResourceQuotaScope defines a filter that must match each object tracked by a quota
+type ResourceQuotaScope string
+
+const (
+ // Match all pod objects where spec.activeDeadlineSeconds >=0
+ ResourceQuotaScopeTerminating ResourceQuotaScope = "Terminating"
+ // Match all pod objects where spec.activeDeadlineSeconds is nil
+ ResourceQuotaScopeNotTerminating ResourceQuotaScope = "NotTerminating"
+ // Match all pod objects that have best effort quality of service
+ ResourceQuotaScopeBestEffort ResourceQuotaScope = "BestEffort"
+ // Match all pod objects that do not have best effort quality of service
+ ResourceQuotaScopeNotBestEffort ResourceQuotaScope = "NotBestEffort"
+ // Match all pod objects that have priority class mentioned
+ ResourceQuotaScopePriorityClass ResourceQuotaScope = "PriorityClass"
+ // Match all pod objects that have cross-namespace pod (anti)affinity mentioned.
+ // This is a beta feature enabled by the PodAffinityNamespaceSelector feature flag.
+ ResourceQuotaScopeCrossNamespacePodAffinity ResourceQuotaScope = "CrossNamespacePodAffinity"
+)
+
+// ResourceQuotaSpec defines the desired hard limits to enforce for Quota.
+type ResourceQuotaSpec struct {
+ // hard is the set of desired hard limits for each named resource.
+ // More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/
+ // +optional
+ Hard ResourceList `json:"hard,omitempty"`
+ // A collection of filters that must match each object tracked by a quota.
+ // If not specified, the quota matches all objects.
+ // +optional
+ Scopes []ResourceQuotaScope `json:"scopes,omitempty"`
+ // scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota
+ // but expressed using ScopeSelectorOperator in combination with possible values.
+ // For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched.
+ // +optional
+ ScopeSelector *ScopeSelector `json:"scopeSelector,omitempty"`
+}
+
+// A scope selector represents the AND of the selectors represented
+// by the scoped-resource selector requirements.
+// +structType=atomic
+type ScopeSelector struct {
+ // A list of scope selector requirements by scope of the resources.
+ // +optional
+ MatchExpressions []ScopedResourceSelectorRequirement `json:"matchExpressions,omitempty"`
+}
+
+// A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator
+// that relates the scope name and values.
+type ScopedResourceSelectorRequirement struct {
+ // The name of the scope that the selector applies to.
+ ScopeName ResourceQuotaScope `json:"scopeName"`
+ // Represents a scope's relationship to a set of values.
+ // Valid operators are In, NotIn, Exists, DoesNotExist.
+ Operator ScopeSelectorOperator `json:"operator"`
+ // An array of string values. If the operator is In or NotIn,
+ // the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ // the values array must be empty.
+ // This array is replaced during a strategic merge patch.
+ // +optional
+ Values []string `json:"values,omitempty"`
+}
+
+// A scope selector operator is the set of operators that can be used in
+// a scope selector requirement.
+type ScopeSelectorOperator string
+
+const (
+ ScopeSelectorOpIn ScopeSelectorOperator = "In"
+ ScopeSelectorOpNotIn ScopeSelectorOperator = "NotIn"
+ ScopeSelectorOpExists ScopeSelectorOperator = "Exists"
+ ScopeSelectorOpDoesNotExist ScopeSelectorOperator = "DoesNotExist"
+)
+
+// ResourceQuotaStatus defines the enforced hard limits and observed use.
+type ResourceQuotaStatus struct {
+ // Hard is the set of enforced hard limits for each named resource.
+ // More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/
+ // +optional
+ Hard ResourceList `json:"hard,omitempty"`
+ // Used is the current observed total usage of the resource in the namespace.
+ // +optional
+ Used ResourceList `json:"used,omitempty"`
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ResourceQuota sets aggregate quota restrictions enforced per namespace
+type ResourceQuota struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Spec defines the desired quota.
+ // https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Spec ResourceQuotaSpec `json:"spec,omitempty"`
+
+ // Status defines the actual enforced quota and its current usage.
+ // https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Status ResourceQuotaStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ResourceQuotaList is a list of ResourceQuota items.
+type ResourceQuotaList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // Items is a list of ResourceQuota objects.
+ // More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/
+ Items []ResourceQuota `json:"items"`
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// Secret holds secret data of a certain type. The total bytes of the values in
+// the Data field must be less than MaxSecretSize bytes.
+type Secret struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Immutable, if set to true, ensures that data stored in the Secret cannot
+ // be updated (only object metadata can be modified).
+ // If not set to true, the field can be modified at any time.
+ // Defaulted to nil.
+ // +optional
+ Immutable *bool `json:"immutable,omitempty"`
+
+ // Data contains the secret data. Each key must consist of alphanumeric
+ // characters, '-', '_' or '.'. The serialized form of the secret data is a
+ // base64 encoded string, representing the arbitrary (possibly non-string)
+ // data value here. Described in https://tools.ietf.org/html/rfc4648#section-4
+ // +optional
+ Data map[string][]byte `json:"data,omitempty"`
+
+ // stringData allows specifying non-binary secret data in string form.
+ // It is provided as a write-only input field for convenience.
+ // All keys and values are merged into the data field on write, overwriting any existing values.
+ // The stringData field is never output when reading from the API.
+ // +k8s:conversion-gen=false
+ // +optional
+ StringData map[string]string `json:"stringData,omitempty"`
+
+ // Used to facilitate programmatic handling of secret data.
+ // +optional
+ Type SecretType `json:"type,omitempty"`
+}
+
+type SecretType string
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// SecretList is a list of Secret.
+type SecretList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // Items is a list of secret objects.
+ // More info: https://kubernetes.io/docs/concepts/configuration/secret
+ Items []Secret `json:"items"`
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ConfigMap holds configuration data for pods to consume.
+type ConfigMap struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Immutable, if set to true, ensures that data stored in the ConfigMap cannot
+ // be updated (only object metadata can be modified).
+ // If not set to true, the field can be modified at any time.
+ // Defaulted to nil.
+ // +optional
+ Immutable *bool `json:"immutable,omitempty"`
+
+ // Data contains the configuration data.
+ // Each key must consist of alphanumeric characters, '-', '_' or '.'.
+ // Values with non-UTF-8 byte sequences must use the BinaryData field.
+ // The keys stored in Data must not overlap with the keys in
+ // the BinaryData field, this is enforced during validation process.
+ // +optional
+ Data map[string]string `json:"data,omitempty"`
+
+ // BinaryData contains the binary data.
+ // Each key must consist of alphanumeric characters, '-', '_' or '.'.
+ // BinaryData can contain byte sequences that are not in the UTF-8 range.
+ // The keys stored in BinaryData must not overlap with the ones in
+ // the Data field, this is enforced during validation process.
+ // Using this field will require 1.10+ apiserver and
+ // kubelet.
+ // +optional
+ BinaryData map[string][]byte `json:"binaryData,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ConfigMapList is a resource containing a list of ConfigMap objects.
+type ConfigMapList struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // Items is the list of ConfigMaps.
+ Items []ConfigMap `json:"items"`
+}
+
+// Type and constants for component health validation.
+type ComponentConditionType string
+
+// These are the valid conditions for the component.
+const (
+ ComponentHealthy ComponentConditionType = "Healthy"
+)
+
+// Information about the condition of a component.
+type ComponentCondition struct {
+ // Type of condition for a component.
+ // Valid value: "Healthy"
+ Type ComponentConditionType `json:"type"`
+ // Status of the condition for a component.
+ // Valid values for "Healthy": "True", "False", or "Unknown".
+ Status ConditionStatus `json:"status"`
+ // Message about the condition for a component.
+ // For example, information about a health check.
+ // +optional
+ Message string `json:"message,omitempty"`
+ // Condition error code for a component.
+ // For example, a health check error code.
+ // +optional
+ Error string `json:"error,omitempty"`
+}
+
+// +genclient
+// +genclient:nonNamespaced
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ComponentStatus (and ComponentStatusList) holds the cluster validation info.
+// Deprecated: This API is deprecated in v1.19+
+type ComponentStatus struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // List of component conditions observed
+ // +optional
+ // +patchMergeKey=type
+ // +patchStrategy=merge
+ Conditions []ComponentCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// Status of all the conditions for the component as a list of ComponentStatus objects.
+// Deprecated: This API is deprecated in v1.19+
+type ComponentStatusList struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ // List of ComponentStatus objects.
+ Items []ComponentStatus `json:"items"`
+}
+
+// DownwardAPIVolumeSource represents a volume containing downward API info.
+// Downward API volumes support ownership management and SELinux relabeling.
+type DownwardAPIVolumeSource struct {
+ // Items is a list of downward API volume file
+ // +optional
+ Items []DownwardAPIVolumeFile `json:"items,omitempty"`
+ // Optional: mode bits to use on created files by default. Must be a
+ // Optional: mode bits used to set permissions on created files by default.
+ // Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511.
+ // YAML accepts both octal and decimal values, JSON requires decimal values for mode bits.
+ // Defaults to 0644.
+ // Directories within the path are not affected by this setting.
+ // This might be in conflict with other options that affect the file
+ // mode, like fsGroup, and the result can be other mode bits set.
+ // +optional
+ DefaultMode *int32 `json:"defaultMode,omitempty"`
+}
+
+const (
+ DownwardAPIVolumeSourceDefaultMode int32 = 0644
+)
+
+// DownwardAPIVolumeFile represents information to create the file containing the pod field
+type DownwardAPIVolumeFile struct {
+ // Required: Path is the relative path name of the file to be created. Must not be absolute or contain the '..' path. Must be utf-8 encoded. The first item of the relative path must not start with '..'
+ Path string `json:"path"`
+ // Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.
+ // +optional
+ FieldRef *ObjectFieldSelector `json:"fieldRef,omitempty"`
+ // Selects a resource of the container: only resources limits and requests
+ // (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.
+ // +optional
+ ResourceFieldRef *ResourceFieldSelector `json:"resourceFieldRef,omitempty"`
+ // Optional: mode bits used to set permissions on this file, must be an octal value
+ // between 0000 and 0777 or a decimal value between 0 and 511.
+ // YAML accepts both octal and decimal values, JSON requires decimal values for mode bits.
+ // If not specified, the volume defaultMode will be used.
+ // This might be in conflict with other options that affect the file
+ // mode, like fsGroup, and the result can be other mode bits set.
+ // +optional
+ Mode *int32 `json:"mode,omitempty"`
+}
+
+// Represents downward API info for projecting into a projected volume.
+// Note that this is identical to a downwardAPI volume source without the default
+// mode.
+type DownwardAPIProjection struct {
+ // Items is a list of DownwardAPIVolume file
+ // +optional
+ Items []DownwardAPIVolumeFile `json:"items,omitempty"`
+}
+
+// SecurityContext holds security configuration that will be applied to a container.
+// Some fields are present in both SecurityContext and PodSecurityContext. When both
+// are set, the values in SecurityContext take precedence.
+type SecurityContext struct {
+ // The capabilities to add/drop when running containers.
+ // Defaults to the default set of capabilities granted by the container runtime.
+ // +optional
+ Capabilities *Capabilities `json:"capabilities,omitempty"`
+ // Run container in privileged mode.
+ // Processes in privileged containers are essentially equivalent to root on the host.
+ // Defaults to false.
+ // +optional
+ Privileged *bool `json:"privileged,omitempty"`
+ // The SELinux context to be applied to the container.
+ // If unspecified, the container runtime will allocate a random SELinux context for each
+ // container. May also be set in PodSecurityContext. If set in both SecurityContext and
+ // PodSecurityContext, the value specified in SecurityContext takes precedence.
+ // +optional
+ SELinuxOptions *SELinuxOptions `json:"seLinuxOptions,omitempty"`
+ // The UID to run the entrypoint of the container process.
+ // Defaults to user specified in image metadata if unspecified.
+ // May also be set in PodSecurityContext. If set in both SecurityContext and
+ // PodSecurityContext, the value specified in SecurityContext takes precedence.
+ // +optional
+ RunAsUser *int64 `json:"runAsUser,omitempty"`
+ // 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.
+ // +optional
+ RunAsGroup *int64 `json:"runAsGroup,omitempty"`
+ // 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.
+ // +optional
+ RunAsNonRoot *bool `json:"runAsNonRoot,omitempty"`
+ // Whether this container has a read-only root filesystem.
+ // Default is false.
+ // +optional
+ ReadOnlyRootFilesystem *bool `json:"readOnlyRootFilesystem,omitempty"`
+ // AllowPrivilegeEscalation controls whether a process can gain more
+ // privileges than its parent process. This bool directly controls if
+ // the no_new_privs flag will be set on the container process.
+ // AllowPrivilegeEscalation is true always when the container is:
+ // 1) run as Privileged
+ // 2) has CAP_SYS_ADMIN
+ // +optional
+ AllowPrivilegeEscalation *bool `json:"allowPrivilegeEscalation,omitempty"`
+ // procMount denotes the type of proc mount to use for the containers.
+ // The default is DefaultProcMount which uses the container runtime defaults for
+ // readonly paths and masked paths.
+ // This requires the ProcMountType feature flag to be enabled.
+ // +optional
+ ProcMount *ProcMountType `json:"procMount,omitempty"`
+ // The seccomp options to use by this container. If seccomp options are
+ // provided at both the pod & container level, the container options
+ // override the pod options.
+ // +optional
+ SeccompProfile *SeccompProfile `json:"seccompProfile,omitempty"`
+}
+
+type ProcMountType string
+
+const (
+ // DefaultProcMount 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.
+ DefaultProcMount ProcMountType = "Default"
+
+ // UnmaskedProcMount bypasses the default masking behavior of the container
+ // runtime and ensures the newly created /proc the container stays in tact with
+ // no modifications.
+ UnmaskedProcMount ProcMountType = "Unmasked"
+)
+
+// SELinuxOptions are the labels to be applied to the container
+type SELinuxOptions struct {
+ // User is a SELinux user label that applies to the container.
+ // +optional
+ User string `json:"user,omitempty"`
+ // Role is a SELinux role label that applies to the container.
+ // +optional
+ Role string `json:"role,omitempty"`
+ // Type is a SELinux type label that applies to the container.
+ // +optional
+ Type string `json:"type,omitempty"`
+ // Level is SELinux level label that applies to the container.
+ // +optional
+ Level string `json:"level,omitempty"`
+}
+
+const (
+ // DefaultSchedulerName defines the name of default scheduler.
+ DefaultSchedulerName = "default-scheduler"
+
+ // RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule
+ // corresponding to every RequiredDuringScheduling affinity rule.
+ // When the --hard-pod-affinity-weight scheduler flag is not specified,
+ // DefaultHardPodAffinityWeight defines the weight of the implicit PreferredDuringScheduling affinity rule.
+ DefaultHardPodAffinitySymmetricWeight int32 = 1
+)
+
+// Sysctl defines a kernel parameter to be set
+type Sysctl struct {
+ // Name of a property to set
+ Name string `json:"name"`
+ // Value of a property to set
+ Value string `json:"value"`
+}
+
+// NodeResources is an object for conveying resource information about a node.
+// see https://kubernetes.io/docs/concepts/architecture/nodes/#capacity for more details.
+type NodeResources struct {
+ // Capacity represents the available resources of a node
+ Capacity ResourceList
+}
+
+const (
+ // Enable stdin for remote command execution
+ ExecStdinParam = "input"
+ // Enable stdout for remote command execution
+ ExecStdoutParam = "output"
+ // Enable stderr for remote command execution
+ ExecStderrParam = "error"
+ // Enable TTY for remote command execution
+ ExecTTYParam = "tty"
+ // Command to run for remote command execution
+ ExecCommandParam = "command"
+
+ // Name of header that specifies stream type
+ StreamType = "streamType"
+ // Value for streamType header for stdin stream
+ StreamTypeStdin = "stdin"
+ // Value for streamType header for stdout stream
+ StreamTypeStdout = "stdout"
+ // Value for streamType header for stderr stream
+ StreamTypeStderr = "stderr"
+ // Value for streamType header for data stream
+ StreamTypeData = "data"
+ // Value for streamType header for error stream
+ StreamTypeError = "error"
+ // Value for streamType header for terminal resize stream
+ StreamTypeResize = "resize"
+
+ // Name of header that specifies the port being forwarded
+ PortHeader = "port"
+ // Name of header that specifies a request ID used to associate the error
+ // and data streams for a single forwarded connection
+ PortForwardRequestIDHeader = "requestID"
+)
+
+// PortStatus represents the error condition of a service port
+
+type PortStatus struct {
+ // Port is the port number of the service port of which status is recorded here
+ Port int32 `json:"port"`
+ // Protocol is the protocol of the service port of which status is recorded here
+ // The supported values are: "TCP", "UDP", "SCTP"
+ Protocol Protocol `json:"protocol"`
+ // Error is to record the problem with the service port
+ // The format of the error shall comply with the following rules:
+ // - built-in error values shall be specified in this file and those shall use
+ // CamelCase names
+ // - cloud provider specific error values must have names that comply with the
+ // format foo.example.com/CamelCase.
+ // ---
+ // The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ // +optional
+ // +kubebuilder:validation:Required
+ // +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
+ // +kubebuilder:validation:MaxLength=316
+ Error *string `json:"error,omitempty"`
+}
diff --git a/pkg/k8s.io/apimachinery/LICENSE b/pkg/k8s.io/apimachinery/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go b/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go
new file mode 100644
index 000000000..a8866a43e
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go
@@ -0,0 +1,299 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package resource
+
+import (
+ "math/big"
+ "strconv"
+
+ inf "gopkg.in/inf.v0"
+)
+
+// Scale is used for getting and setting the base-10 scaled value.
+// Base-2 scales are omitted for mathematical simplicity.
+// See Quantity.ScaledValue for more details.
+type Scale int32
+
+// infScale adapts a Scale value to an inf.Scale value.
+func (s Scale) infScale() inf.Scale {
+ return inf.Scale(-s) // inf.Scale is upside-down
+}
+
+const (
+ Nano Scale = -9
+ Micro Scale = -6
+ Milli Scale = -3
+ Kilo Scale = 3
+ Mega Scale = 6
+ Giga Scale = 9
+ Tera Scale = 12
+ Peta Scale = 15
+ Exa Scale = 18
+)
+
+var (
+ Zero = int64Amount{}
+
+ // Used by quantity strings - treat as read only
+ zeroBytes = []byte("0")
+)
+
+// int64Amount represents a fixed precision numerator and arbitrary scale exponent. It is faster
+// than operations on inf.Dec for values that can be represented as int64.
+// +k8s:openapi-gen=true
+type int64Amount struct {
+ value int64
+ scale Scale
+}
+
+// Sign returns 0 if the value is zero, -1 if it is less than 0, or 1 if it is greater than 0.
+func (a int64Amount) Sign() int {
+ switch {
+ case a.value == 0:
+ return 0
+ case a.value > 0:
+ return 1
+ default:
+ return -1
+ }
+}
+
+// AsInt64 returns the current amount as an int64 at scale 0, or false if the value cannot be
+// represented in an int64 OR would result in a loss of precision. This method is intended as
+// an optimization to avoid calling AsDec.
+func (a int64Amount) AsInt64() (int64, bool) {
+ if a.scale == 0 {
+ return a.value, true
+ }
+ if a.scale < 0 {
+ // TODO: attempt to reduce factors, although it is assumed that factors are reduced prior
+ // to the int64Amount being created.
+ return 0, false
+ }
+ return positiveScaleInt64(a.value, a.scale)
+}
+
+// AsScaledInt64 returns an int64 representing the value of this amount at the specified scale,
+// rounding up, or false if that would result in overflow. (1e20).AsScaledInt64(1) would result
+// in overflow because 1e19 is not representable as an int64. Note that setting a scale larger
+// than the current value may result in loss of precision - i.e. (1e-6).AsScaledInt64(0) would
+// return 1, because 0.000001 is rounded up to 1.
+func (a int64Amount) AsScaledInt64(scale Scale) (result int64, ok bool) {
+ if a.scale < scale {
+ result, _ = negativeScaleInt64(a.value, scale-a.scale)
+ return result, true
+ }
+ return positiveScaleInt64(a.value, a.scale-scale)
+}
+
+// AsDec returns an inf.Dec representation of this value.
+func (a int64Amount) AsDec() *inf.Dec {
+ var base inf.Dec
+ base.SetUnscaled(a.value)
+ base.SetScale(inf.Scale(-a.scale))
+ return &base
+}
+
+// Cmp returns 0 if a and b are equal, 1 if a is greater than b, or -1 if a is less than b.
+func (a int64Amount) Cmp(b int64Amount) int {
+ switch {
+ case a.scale == b.scale:
+ // compare only the unscaled portion
+ case a.scale > b.scale:
+ result, remainder, exact := divideByScaleInt64(b.value, a.scale-b.scale)
+ if !exact {
+ return a.AsDec().Cmp(b.AsDec())
+ }
+ if result == a.value {
+ switch {
+ case remainder == 0:
+ return 0
+ case remainder > 0:
+ return -1
+ default:
+ return 1
+ }
+ }
+ b.value = result
+ default:
+ result, remainder, exact := divideByScaleInt64(a.value, b.scale-a.scale)
+ if !exact {
+ return a.AsDec().Cmp(b.AsDec())
+ }
+ if result == b.value {
+ switch {
+ case remainder == 0:
+ return 0
+ case remainder > 0:
+ return 1
+ default:
+ return -1
+ }
+ }
+ a.value = result
+ }
+
+ switch {
+ case a.value == b.value:
+ return 0
+ case a.value < b.value:
+ return -1
+ default:
+ return 1
+ }
+}
+
+// Add adds two int64Amounts together, matching scales. It will return false and not mutate
+// a if overflow or underflow would result.
+func (a *int64Amount) Add(b int64Amount) bool {
+ switch {
+ case b.value == 0:
+ return true
+ case a.value == 0:
+ a.value = b.value
+ a.scale = b.scale
+ return true
+ case a.scale == b.scale:
+ c, ok := int64Add(a.value, b.value)
+ if !ok {
+ return false
+ }
+ a.value = c
+ case a.scale > b.scale:
+ c, ok := positiveScaleInt64(a.value, a.scale-b.scale)
+ if !ok {
+ return false
+ }
+ c, ok = int64Add(c, b.value)
+ if !ok {
+ return false
+ }
+ a.scale = b.scale
+ a.value = c
+ default:
+ c, ok := positiveScaleInt64(b.value, b.scale-a.scale)
+ if !ok {
+ return false
+ }
+ c, ok = int64Add(a.value, c)
+ if !ok {
+ return false
+ }
+ a.value = c
+ }
+ return true
+}
+
+// Sub removes the value of b from the current amount, or returns false if underflow would result.
+func (a *int64Amount) Sub(b int64Amount) bool {
+ return a.Add(int64Amount{value: -b.value, scale: b.scale})
+}
+
+// AsScale adjusts this amount to set a minimum scale, rounding up, and returns true iff no precision
+// was lost. (1.1e5).AsScale(5) would return 1.1e5, but (1.1e5).AsScale(6) would return 1e6.
+func (a int64Amount) AsScale(scale Scale) (int64Amount, bool) {
+ if a.scale >= scale {
+ return a, true
+ }
+ result, exact := negativeScaleInt64(a.value, scale-a.scale)
+ return int64Amount{value: result, scale: scale}, exact
+}
+
+// AsCanonicalBytes accepts a buffer to write the base-10 string value of this field to, and returns
+// either that buffer or a larger buffer and the current exponent of the value. The value is adjusted
+// until the exponent is a multiple of 3 - i.e. 1.1e5 would return "110", 3.
+func (a int64Amount) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
+ mantissa := a.value
+ exponent = int32(a.scale)
+
+ amount, times := removeInt64Factors(mantissa, 10)
+ exponent += int32(times)
+
+ // make sure exponent is a multiple of 3
+ var ok bool
+ switch exponent % 3 {
+ case 1, -2:
+ amount, ok = int64MultiplyScale10(amount)
+ if !ok {
+ return infDecAmount{a.AsDec()}.AsCanonicalBytes(out)
+ }
+ exponent = exponent - 1
+ case 2, -1:
+ amount, ok = int64MultiplyScale100(amount)
+ if !ok {
+ return infDecAmount{a.AsDec()}.AsCanonicalBytes(out)
+ }
+ exponent = exponent - 2
+ }
+ return strconv.AppendInt(out, amount, 10), exponent
+}
+
+// AsCanonicalBase1024Bytes accepts a buffer to write the base-1024 string value of this field to, and returns
+// either that buffer or a larger buffer and the current exponent of the value. 2048 is 2 * 1024 ^ 1 and would
+// return []byte("2048"), 1.
+func (a int64Amount) AsCanonicalBase1024Bytes(out []byte) (result []byte, exponent int32) {
+ value, ok := a.AsScaledInt64(0)
+ if !ok {
+ return infDecAmount{a.AsDec()}.AsCanonicalBase1024Bytes(out)
+ }
+ amount, exponent := removeInt64Factors(value, 1024)
+ return strconv.AppendInt(out, amount, 10), exponent
+}
+
+// infDecAmount implements common operations over an inf.Dec that are specific to the quantity
+// representation.
+type infDecAmount struct {
+ *inf.Dec
+}
+
+// AsScale adjusts this amount to set a minimum scale, rounding up, and returns true iff no precision
+// was lost. (1.1e5).AsScale(5) would return 1.1e5, but (1.1e5).AsScale(6) would return 1e6.
+func (a infDecAmount) AsScale(scale Scale) (infDecAmount, bool) {
+ tmp := &inf.Dec{}
+ tmp.Round(a.Dec, scale.infScale(), inf.RoundUp)
+ return infDecAmount{tmp}, tmp.Cmp(a.Dec) == 0
+}
+
+// AsCanonicalBytes accepts a buffer to write the base-10 string value of this field to, and returns
+// either that buffer or a larger buffer and the current exponent of the value. The value is adjusted
+// until the exponent is a multiple of 3 - i.e. 1.1e5 would return "110", 3.
+func (a infDecAmount) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
+ mantissa := a.Dec.UnscaledBig()
+ exponent = int32(-a.Dec.Scale())
+ amount := big.NewInt(0).Set(mantissa)
+ // move all factors of 10 into the exponent for easy reasoning
+ amount, times := removeBigIntFactors(amount, bigTen)
+ exponent += times
+
+ // make sure exponent is a multiple of 3
+ for exponent%3 != 0 {
+ amount.Mul(amount, bigTen)
+ exponent--
+ }
+
+ return append(out, amount.String()...), exponent
+}
+
+// AsCanonicalBase1024Bytes accepts a buffer to write the base-1024 string value of this field to, and returns
+// either that buffer or a larger buffer and the current exponent of the value. 2048 is 2 * 1024 ^ 1 and would
+// return []byte("2048"), 1.
+func (a infDecAmount) AsCanonicalBase1024Bytes(out []byte) (result []byte, exponent int32) {
+ tmp := &inf.Dec{}
+ tmp.Round(a.Dec, 0, inf.RoundUp)
+ amount, exponent := removeBigIntFactors(tmp.UnscaledBig(), big1024)
+ return append(out, amount.String()...), exponent
+}
diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/math.go b/pkg/k8s.io/apimachinery/pkg/api/resource/math.go
new file mode 100644
index 000000000..7b4fa5a36
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/pkg/api/resource/math.go
@@ -0,0 +1,304 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package resource
+
+import (
+ "math/big"
+
+ inf "gopkg.in/inf.v0"
+)
+
+const (
+ // maxInt64Factors is the highest value that will be checked when removing factors of 10 from an int64.
+ // It is also the maximum decimal digits that can be represented with an int64.
+ maxInt64Factors = 18
+)
+
+var (
+ // Commonly needed big.Int values-- treat as read only!
+ bigTen = big.NewInt(10)
+ bigZero = big.NewInt(0)
+ bigOne = big.NewInt(1)
+ big1024 = big.NewInt(1024)
+
+ // Commonly needed inf.Dec values-- treat as read only!
+ decZero = inf.NewDec(0, 0)
+ decOne = inf.NewDec(1, 0)
+
+ // Largest (in magnitude) number allowed.
+ maxAllowed = infDecAmount{inf.NewDec((1<<63)-1, 0)} // == max int64
+)
+
+const mostNegative = -(mostPositive + 1)
+const mostPositive = 1<<63 - 1
+
+// int64Add returns a+b, or false if that would overflow int64.
+func int64Add(a, b int64) (int64, bool) {
+ c := a + b
+ switch {
+ case a > 0 && b > 0:
+ if c < 0 {
+ return 0, false
+ }
+ case a < 0 && b < 0:
+ if c > 0 {
+ return 0, false
+ }
+ if a == mostNegative && b == mostNegative {
+ return 0, false
+ }
+ }
+ return c, true
+}
+
+// int64Multiply returns a*b, or false if that would overflow or underflow int64.
+func int64Multiply(a, b int64) (int64, bool) {
+ if a == 0 || b == 0 || a == 1 || b == 1 {
+ return a * b, true
+ }
+ if a == mostNegative || b == mostNegative {
+ return 0, false
+ }
+ c := a * b
+ return c, c/b == a
+}
+
+// int64MultiplyScale returns a*b, assuming b is greater than one, or false if that would overflow or underflow int64.
+// Use when b is known to be greater than one.
+func int64MultiplyScale(a int64, b int64) (int64, bool) {
+ if a == 0 || a == 1 {
+ return a * b, true
+ }
+ if a == mostNegative && b != 1 {
+ return 0, false
+ }
+ c := a * b
+ return c, c/b == a
+}
+
+// int64MultiplyScale10 multiplies a by 10, or returns false if that would overflow. This method is faster than
+// int64Multiply(a, 10) because the compiler can optimize constant factor multiplication.
+func int64MultiplyScale10(a int64) (int64, bool) {
+ if a == 0 || a == 1 {
+ return a * 10, true
+ }
+ if a == mostNegative {
+ return 0, false
+ }
+ c := a * 10
+ return c, c/10 == a
+}
+
+// int64MultiplyScale100 multiplies a by 100, or returns false if that would overflow. This method is faster than
+// int64Multiply(a, 100) because the compiler can optimize constant factor multiplication.
+func int64MultiplyScale100(a int64) (int64, bool) {
+ if a == 0 || a == 1 {
+ return a * 100, true
+ }
+ if a == mostNegative {
+ return 0, false
+ }
+ c := a * 100
+ return c, c/100 == a
+}
+
+// int64MultiplyScale1000 multiplies a by 1000, or returns false if that would overflow. This method is faster than
+// int64Multiply(a, 1000) because the compiler can optimize constant factor multiplication.
+func int64MultiplyScale1000(a int64) (int64, bool) {
+ if a == 0 || a == 1 {
+ return a * 1000, true
+ }
+ if a == mostNegative {
+ return 0, false
+ }
+ c := a * 1000
+ return c, c/1000 == a
+}
+
+// positiveScaleInt64 multiplies base by 10^scale, returning false if the
+// value overflows. Passing a negative scale is undefined.
+func positiveScaleInt64(base int64, scale Scale) (int64, bool) {
+ switch scale {
+ case 0:
+ return base, true
+ case 1:
+ return int64MultiplyScale10(base)
+ case 2:
+ return int64MultiplyScale100(base)
+ case 3:
+ return int64MultiplyScale1000(base)
+ case 6:
+ return int64MultiplyScale(base, 1000000)
+ case 9:
+ return int64MultiplyScale(base, 1000000000)
+ default:
+ value := base
+ var ok bool
+ for i := Scale(0); i < scale; i++ {
+ if value, ok = int64MultiplyScale(value, 10); !ok {
+ return 0, false
+ }
+ }
+ return value, true
+ }
+}
+
+// negativeScaleInt64 reduces base by the provided scale, rounding up, until the
+// value is zero or the scale is reached. Passing a negative scale is undefined.
+// The value returned, if not exact, is rounded away from zero.
+func negativeScaleInt64(base int64, scale Scale) (result int64, exact bool) {
+ if scale == 0 {
+ return base, true
+ }
+
+ value := base
+ var fraction bool
+ for i := Scale(0); i < scale; i++ {
+ if !fraction && value%10 != 0 {
+ fraction = true
+ }
+ value = value / 10
+ if value == 0 {
+ if fraction {
+ if base > 0 {
+ return 1, false
+ }
+ return -1, false
+ }
+ return 0, true
+ }
+ }
+ if fraction {
+ if base > 0 {
+ value++
+ } else {
+ value--
+ }
+ }
+ return value, !fraction
+}
+
+func pow10Int64(b int64) int64 {
+ switch b {
+ case 0:
+ return 1
+ case 1:
+ return 10
+ case 2:
+ return 100
+ case 3:
+ return 1000
+ case 4:
+ return 10000
+ case 5:
+ return 100000
+ case 6:
+ return 1000000
+ case 7:
+ return 10000000
+ case 8:
+ return 100000000
+ case 9:
+ return 1000000000
+ case 10:
+ return 10000000000
+ case 11:
+ return 100000000000
+ case 12:
+ return 1000000000000
+ case 13:
+ return 10000000000000
+ case 14:
+ return 100000000000000
+ case 15:
+ return 1000000000000000
+ case 16:
+ return 10000000000000000
+ case 17:
+ return 100000000000000000
+ case 18:
+ return 1000000000000000000
+ default:
+ return 0
+ }
+}
+
+// negativeScaleInt64 returns the result of dividing base by scale * 10 and the remainder, or
+// false if no such division is possible. Dividing by negative scales is undefined.
+func divideByScaleInt64(base int64, scale Scale) (result, remainder int64, exact bool) {
+ if scale == 0 {
+ return base, 0, true
+ }
+ // the max scale representable in base 10 in an int64 is 18 decimal places
+ if scale >= 18 {
+ return 0, base, false
+ }
+ divisor := pow10Int64(int64(scale))
+ return base / divisor, base % divisor, true
+}
+
+// removeInt64Factors divides in a loop; the return values have the property that
+// value == result * base ^ scale
+func removeInt64Factors(value int64, base int64) (result int64, times int32) {
+ times = 0
+ result = value
+ negative := result < 0
+ if negative {
+ result = -result
+ }
+ switch base {
+ // allow the compiler to optimize the common cases
+ case 10:
+ for result >= 10 && result%10 == 0 {
+ times++
+ result = result / 10
+ }
+ // allow the compiler to optimize the common cases
+ case 1024:
+ for result >= 1024 && result%1024 == 0 {
+ times++
+ result = result / 1024
+ }
+ default:
+ for result >= base && result%base == 0 {
+ times++
+ result = result / base
+ }
+ }
+ if negative {
+ result = -result
+ }
+ return result, times
+}
+
+// removeBigIntFactors divides in a loop; the return values have the property that
+// d == result * factor ^ times
+// d may be modified in place.
+// If d == 0, then the return values will be (0, 0)
+func removeBigIntFactors(d, factor *big.Int) (result *big.Int, times int32) {
+ q := big.NewInt(0)
+ m := big.NewInt(0)
+ for d.Cmp(bigZero) != 0 {
+ q.DivMod(d, factor, m)
+ if m.Cmp(bigZero) != 0 {
+ break
+ }
+ times++
+ d, q = q, d
+ }
+ return d, times
+}
diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go b/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go
new file mode 100644
index 000000000..352cc028f
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go
@@ -0,0 +1,693 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package resource
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "math"
+ "math/big"
+ "strconv"
+ "strings"
+
+ inf "gopkg.in/inf.v0"
+)
+
+// 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.
+//
+// The serialization format is:
+//
+// <quantity> ::= <signedNumber><suffix>
+// (Note that <suffix> may be empty, from the "" case in <decimalSI>.)
+// <digit> ::= 0 | 1 | ... | 9
+// <digits> ::= <digit> | <digit><digits>
+// <number> ::= <digits> | <digits>.<digits> | <digits>. | .<digits>
+// <sign> ::= "+" | "-"
+// <signedNumber> ::= <number> | <sign><number>
+// <suffix> ::= <binarySI> | <decimalExponent> | <decimalSI>
+// <binarySI> ::= Ki | Mi | Gi | Ti | Pi | Ei
+// (International System of units; See: http://physics.nist.gov/cuu/Units/binary.html)
+// <decimalSI> ::= m | "" | k | M | G | T | P | E
+// (Note that 1024 = 1Ki but 1000 = 1k; I didn't choose the capitalization.)
+// <decimalExponent> ::= "e" <signedNumber> | "E" <signedNumber>
+//
+// No 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.
+//
+// When 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.
+//
+// Before 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:
+// a. No precision is lost
+// b. No fractional digits will be emitted
+// c. The exponent (or suffix) is as large as possible.
+// The sign will be omitted unless the number is negative.
+//
+// Examples:
+// 1.5 will be serialized as "1500m"
+// 1.5Gi will be serialized as "1536Mi"
+//
+// Note that the quantity will NEVER be internally represented by a
+// floating point number. That is the whole point of this exercise.
+//
+// Non-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.)
+//
+// This 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.
+//
+// +protobuf=true
+// +protobuf.embed=string
+// +protobuf.options.marshal=false
+// +protobuf.options.(gogoproto.goproto_stringer)=false
+// +k8s:deepcopy-gen=true
+// +k8s:openapi-gen=true
+type Quantity struct {
+ // i is the quantity in int64 scaled form, if d.Dec == nil
+ i int64Amount
+ // d is the quantity in inf.Dec form if d.Dec != nil
+ d infDecAmount
+ // s is the generated value of this quantity to avoid recalculation
+ s string
+
+ // Change Format at will. See the comment for Canonicalize for
+ // more details.
+ Format
+}
+
+// CanonicalValue allows a quantity amount to be converted to a string.
+type CanonicalValue interface {
+ // AsCanonicalBytes returns a byte array representing the string representation
+ // of the value mantissa and an int32 representing its exponent in base-10. Callers may
+ // pass a byte slice to the method to avoid allocations.
+ AsCanonicalBytes(out []byte) ([]byte, int32)
+ // AsCanonicalBase1024Bytes returns a byte array representing the string representation
+ // of the value mantissa and an int32 representing its exponent in base-1024. Callers
+ // may pass a byte slice to the method to avoid allocations.
+ AsCanonicalBase1024Bytes(out []byte) ([]byte, int32)
+}
+
+// Format lists the three possible formattings of a quantity.
+type Format string
+
+const (
+ DecimalExponent = Format("DecimalExponent") // e.g., 12e6
+ BinarySI = Format("BinarySI") // e.g., 12Mi (12 * 2^20)
+ DecimalSI = Format("DecimalSI") // e.g., 12M (12 * 10^6)
+)
+
+// MustParse turns the given string into a quantity or panics; for tests
+// or other cases where you know the string is valid.
+func MustParse(str string) Quantity {
+ q, err := ParseQuantity(str)
+ if err != nil {
+ panic(fmt.Errorf("cannot parse '%v': %v", str, err))
+ }
+ return q
+}
+
+const (
+ // splitREString is used to separate a number from its suffix; as such,
+ // this is overly permissive, but that's OK-- it will be checked later.
+ splitREString = "^([+-]?[0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$"
+)
+
+var (
+ // Errors that could happen while parsing a string.
+ // nolint:golint
+ ErrFormatWrong = errors.New("quantities must match the regular expression '" + splitREString + "'")
+ ErrNumeric = errors.New("unable to parse numeric part of quantity")
+ ErrSuffix = errors.New("unable to parse quantity's suffix")
+)
+
+// parseQuantityString is a fast scanner for quantity values.
+func parseQuantityString(str string) (positive bool, value, num, denom, suffix string, err error) {
+ positive = true
+ pos := 0
+ end := len(str)
+
+ // handle leading sign
+ if pos < end {
+ switch str[0] {
+ case '-':
+ positive = false
+ pos++
+ case '+':
+ pos++
+ }
+ }
+
+ // strip leading zeros
+Zeroes:
+ for i := pos; ; i++ {
+ if i >= end {
+ num = "0"
+ value = num
+ return
+ }
+ switch str[i] {
+ case '0':
+ pos++
+ default:
+ break Zeroes
+ }
+ }
+
+ // extract the numerator
+Num:
+ for i := pos; ; i++ {
+ if i >= end {
+ num = str[pos:end]
+ value = str[0:end]
+ return
+ }
+ switch str[i] {
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ default:
+ num = str[pos:i]
+ pos = i
+ break Num
+ }
+ }
+
+ // if we stripped all numerator positions, always return 0
+ if len(num) == 0 {
+ num = "0"
+ }
+
+ // handle a denominator
+ if pos < end && str[pos] == '.' {
+ pos++
+ Denom:
+ for i := pos; ; i++ {
+ if i >= end {
+ denom = str[pos:end]
+ value = str[0:end]
+ return
+ }
+ switch str[i] {
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ default:
+ denom = str[pos:i]
+ pos = i
+ break Denom
+ }
+ }
+ // TODO: we currently allow 1.G, but we may not want to in the future.
+ // if len(denom) == 0 {
+ // err = ErrFormatWrong
+ // return
+ // }
+ }
+ value = str[0:pos]
+
+ // grab the elements of the suffix
+ suffixStart := pos
+ for i := pos; ; i++ {
+ if i >= end {
+ suffix = str[suffixStart:end]
+ return
+ }
+ if !strings.ContainsAny(str[i:i+1], "eEinumkKMGTP") {
+ pos = i
+ break
+ }
+ }
+ if pos < end {
+ switch str[pos] {
+ case '-', '+':
+ pos++
+ }
+ }
+Suffix:
+ for i := pos; ; i++ {
+ if i >= end {
+ suffix = str[suffixStart:end]
+ return
+ }
+ switch str[i] {
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ default:
+ break Suffix
+ }
+ }
+ // we encountered a non decimal in the Suffix loop, but the last character
+ // was not a valid exponent
+ err = ErrFormatWrong
+ // nolint:nakedret
+ return
+}
+
+// ParseQuantity turns str into a Quantity, or returns an error.
+func ParseQuantity(str string) (Quantity, error) {
+ if len(str) == 0 {
+ return Quantity{}, ErrFormatWrong
+ }
+ if str == "0" {
+ return Quantity{Format: DecimalSI, s: str}, nil
+ }
+
+ positive, value, num, denom, suf, err := parseQuantityString(str)
+ if err != nil {
+ return Quantity{}, err
+ }
+
+ base, exponent, format, ok := quantitySuffixer.interpret(suffix(suf))
+ if !ok {
+ return Quantity{}, ErrSuffix
+ }
+
+ precision := int32(0)
+ scale := int32(0)
+ mantissa := int64(1)
+ switch format {
+ case DecimalExponent, DecimalSI:
+ scale = exponent
+ precision = maxInt64Factors - int32(len(num)+len(denom))
+ case BinarySI:
+ scale = 0
+ switch {
+ case exponent >= 0 && len(denom) == 0:
+ // only handle positive binary numbers with the fast path
+ mantissa = int64(int64(mantissa) << uint64(exponent))
+ // 1Mi (2^20) has ~6 digits of decimal precision, so exponent*3/10 -1 is roughly the precision
+ precision = 15 - int32(len(num)) - int32(float32(exponent)*3/10) - 1
+ default:
+ precision = -1
+ }
+ }
+
+ if precision >= 0 {
+ // if we have a denominator, shift the entire value to the left by the number of places in the
+ // denominator
+ scale -= int32(len(denom))
+ if scale >= int32(Nano) {
+ shifted := num + denom
+
+ var value int64
+ value, err := strconv.ParseInt(shifted, 10, 64)
+ if err != nil {
+ return Quantity{}, ErrNumeric
+ }
+ if result, ok := int64Multiply(value, int64(mantissa)); ok {
+ if !positive {
+ result = -result
+ }
+ // if the number is in canonical form, reuse the string
+ switch format {
+ case BinarySI:
+ if exponent%10 == 0 && (value&0x07 != 0) {
+ return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format, s: str}, nil
+ }
+ default:
+ if scale%3 == 0 && !strings.HasSuffix(shifted, "000") && shifted[0] != '0' {
+ return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format, s: str}, nil
+ }
+ }
+ return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format}, nil
+ }
+ }
+ }
+
+ amount := new(inf.Dec)
+ if _, ok := amount.SetString(value); !ok {
+ return Quantity{}, ErrNumeric
+ }
+
+ // So that no one but us has to think about suffixes, remove it.
+ if base == 10 {
+ amount.SetScale(amount.Scale() + Scale(exponent).infScale())
+ } else if base == 2 {
+ // numericSuffix = 2 ** exponent
+ numericSuffix := big.NewInt(1).Lsh(bigOne, uint(exponent))
+ ub := amount.UnscaledBig()
+ amount.SetUnscaledBig(ub.Mul(ub, numericSuffix))
+ }
+
+ // Cap at min/max bounds.
+ sign := amount.Sign()
+ if sign == -1 {
+ amount.Neg(amount)
+ }
+
+ // This rounds non-zero values up to the minimum representable value, under the theory that
+ // if you want some resources, you should get some resources, even if you asked for way too small
+ // of an amount. Arguably, this should be inf.RoundHalfUp (normal rounding), but that would have
+ // the side effect of rounding values < .5n to zero.
+ if v, ok := amount.Unscaled(); v != int64(0) || !ok {
+ amount.Round(amount, Nano.infScale(), inf.RoundUp)
+ }
+
+ // The max is just a simple cap.
+ // TODO: this prevents accumulating quantities greater than int64, for instance quota across a cluster
+ if format == BinarySI && amount.Cmp(maxAllowed.Dec) > 0 {
+ amount.Set(maxAllowed.Dec)
+ }
+
+ if format == BinarySI && amount.Cmp(decOne) < 0 && amount.Cmp(decZero) > 0 {
+ // This avoids rounding and hopefully confusion, too.
+ format = DecimalSI
+ }
+ if sign == -1 {
+ amount.Neg(amount)
+ }
+
+ return Quantity{d: infDecAmount{amount}, Format: format}, nil
+}
+
+// DeepCopy returns a deep-copy of the Quantity value. Note that the method
+// receiver is a value, so we can mutate it in-place and return it.
+func (q Quantity) DeepCopy() Quantity {
+ if q.d.Dec != nil {
+ tmp := &inf.Dec{}
+ q.d.Dec = tmp.Set(q.d.Dec)
+ }
+ return q
+}
+
+// CanonicalizeBytes returns the canonical form of q and its suffix (see comment on Quantity).
+//
+// Note about BinarySI:
+// * If q.Format is set to BinarySI and q.Amount represents a non-zero value between
+// -1 and +1, it will be emitted as if q.Format were DecimalSI.
+// * Otherwise, if q.Format is set to BinarySI, fractional parts of q.Amount will be
+// rounded up. (1.1i becomes 2i.)
+func (q *Quantity) CanonicalizeBytes(out []byte) (result, suffix []byte) {
+ if q.IsZero() {
+ return zeroBytes, nil
+ }
+
+ var rounded CanonicalValue
+ format := q.Format
+ switch format {
+ case DecimalExponent, DecimalSI:
+ case BinarySI:
+ if q.CmpInt64(-1024) > 0 && q.CmpInt64(1024) < 0 {
+ // This avoids rounding and hopefully confusion, too.
+ format = DecimalSI
+ } else {
+ var exact bool
+ if rounded, exact = q.AsScale(0); !exact {
+ // Don't lose precision-- show as DecimalSI
+ format = DecimalSI
+ }
+ }
+ default:
+ format = DecimalExponent
+ }
+
+ // TODO: If BinarySI formatting is requested but would cause rounding, upgrade to
+ // one of the other formats.
+ switch format {
+ case DecimalExponent, DecimalSI:
+ number, exponent := q.AsCanonicalBytes(out)
+ suffix, _ := quantitySuffixer.constructBytes(10, exponent, format)
+ return number, suffix
+ default:
+ // format must be BinarySI
+ number, exponent := rounded.AsCanonicalBase1024Bytes(out)
+ suffix, _ := quantitySuffixer.constructBytes(2, exponent*10, format)
+ return number, suffix
+ }
+}
+
+// AsApproximateFloat64 returns a float64 representation of the quantity which may
+// lose precision. If the value of the quantity is outside the range of a float64
+// +Inf/-Inf will be returned.
+func (q *Quantity) AsApproximateFloat64() float64 {
+ var base float64
+ var exponent int
+ if q.d.Dec != nil {
+ base, _ = big.NewFloat(0).SetInt(q.d.Dec.UnscaledBig()).Float64()
+ exponent = int(-q.d.Dec.Scale())
+ } else {
+ base = float64(q.i.value)
+ exponent = int(q.i.scale)
+ }
+ if exponent == 0 {
+ return base
+ }
+
+ // multiply by the appropriate exponential scale
+ switch q.Format {
+ case DecimalExponent, DecimalSI:
+ return base * math.Pow10(exponent)
+ default:
+ // fast path for exponents that can fit in 64 bits
+ if exponent > 0 && exponent < 7 {
+ return base * float64(int64(1)<<(exponent*10))
+ }
+ return base * math.Pow(2, float64(exponent*10))
+ }
+}
+
+// AsInt64 returns a representation of the current value as an int64 if a fast conversion
+// is possible. If false is returned, callers must use the inf.Dec form of this quantity.
+func (q *Quantity) AsInt64() (int64, bool) {
+ if q.d.Dec != nil {
+ return 0, false
+ }
+ return q.i.AsInt64()
+}
+
+// ToDec promotes the quantity in place to use an inf.Dec representation and returns itself.
+func (q *Quantity) ToDec() *Quantity {
+ if q.d.Dec == nil {
+ q.d.Dec = q.i.AsDec()
+ q.i = int64Amount{}
+ }
+ return q
+}
+
+// AsDec returns the quantity as represented by a scaled inf.Dec.
+func (q *Quantity) AsDec() *inf.Dec {
+ if q.d.Dec != nil {
+ return q.d.Dec
+ }
+ q.d.Dec = q.i.AsDec()
+ q.i = int64Amount{}
+ return q.d.Dec
+}
+
+// AsCanonicalBytes returns the canonical byte representation of this quantity as a mantissa
+// and base 10 exponent. The out byte slice may be passed to the method to avoid an extra
+// allocation.
+func (q *Quantity) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
+ if q.d.Dec != nil {
+ return q.d.AsCanonicalBytes(out)
+ }
+ return q.i.AsCanonicalBytes(out)
+}
+
+// IsZero returns true if the quantity is equal to zero.
+func (q *Quantity) IsZero() bool {
+ if q.d.Dec != nil {
+ return q.d.Dec.Sign() == 0
+ }
+ return q.i.value == 0
+}
+
+// AsScale returns the current value, rounded up to the provided scale, and returns
+// false if the scale resulted in a loss of precision.
+func (q *Quantity) AsScale(scale Scale) (CanonicalValue, bool) {
+ if q.d.Dec != nil {
+ return q.d.AsScale(scale)
+ }
+ return q.i.AsScale(scale)
+}
+
+// Cmp returns 0 if the quantity is equal to y, -1 if the quantity is less than y, or 1 if the
+// quantity is greater than y.
+func (q *Quantity) Cmp(y Quantity) int {
+ if q.d.Dec == nil && y.d.Dec == nil {
+ return q.i.Cmp(y.i)
+ }
+ return q.AsDec().Cmp(y.AsDec())
+}
+
+// CmpInt64 returns 0 if the quantity is equal to y, -1 if the quantity is less than y, or 1 if the
+// quantity is greater than y.
+func (q *Quantity) CmpInt64(y int64) int {
+ if q.d.Dec != nil {
+ return q.d.Dec.Cmp(inf.NewDec(y, inf.Scale(0)))
+ }
+ return q.i.Cmp(int64Amount{value: y})
+}
+
+// int64QuantityExpectedBytes is the expected width in bytes of the canonical string representation
+// of most Quantity values.
+const int64QuantityExpectedBytes = 18
+
+// String formats the Quantity as a string, caching the result if not calculated.
+// String is an expensive operation and caching this result significantly reduces the cost of
+// normal parse / marshal operations on Quantity.
+func (q *Quantity) String() string {
+ if q == nil {
+ return "<nil>"
+ }
+ if len(q.s) == 0 {
+ result := make([]byte, 0, int64QuantityExpectedBytes)
+ number, suffix := q.CanonicalizeBytes(result)
+ number = append(number, suffix...)
+ q.s = string(number)
+ }
+ return q.s
+}
+
+// MarshalJSON implements the json.Marshaller interface.
+func (q Quantity) MarshalJSON() ([]byte, error) {
+ if len(q.s) > 0 {
+ out := make([]byte, len(q.s)+2)
+ out[0], out[len(out)-1] = '"', '"'
+ copy(out[1:], q.s)
+ return out, nil
+ }
+ result := make([]byte, int64QuantityExpectedBytes)
+ result[0] = '"'
+ number, suffix := q.CanonicalizeBytes(result[1:1])
+ // if the same slice was returned to us that we passed in, avoid another allocation by copying number into
+ // the source slice and returning that
+ if len(number) > 0 && &number[0] == &result[1] && (len(number)+len(suffix)+2) <= int64QuantityExpectedBytes {
+ number = append(number, suffix...)
+ number = append(number, '"')
+ return result[:1+len(number)], nil
+ }
+ // if CanonicalizeBytes needed more space than our slice provided, we may need to allocate again so use
+ // append
+ result = result[:1]
+ result = append(result, number...) // nolint: makezero
+ result = append(result, suffix...) // nolint: makezero
+ result = append(result, '"') // nolint: makezero
+ return result, nil
+}
+
+// ToUnstructured implements the value.UnstructuredConverter interface.
+func (q Quantity) ToUnstructured() interface{} {
+ return q.String()
+}
+
+// UnmarshalJSON implements the json.Unmarshaller interface.
+// TODO: Remove support for leading/trailing whitespace
+func (q *Quantity) UnmarshalJSON(value []byte) error {
+ l := len(value)
+ if l == 4 && bytes.Equal(value, []byte("null")) {
+ q.d.Dec = nil
+ q.i = int64Amount{}
+ return nil
+ }
+ if l >= 2 && value[0] == '"' && value[l-1] == '"' {
+ value = value[1 : l-1]
+ }
+
+ parsed, err := ParseQuantity(strings.TrimSpace(string(value)))
+ if err != nil {
+ return err
+ }
+
+ // This copy is safe because parsed will not be referred to again.
+ *q = parsed
+ return nil
+}
+
+// NewDecimalQuantity returns a new Quantity representing the given
+// value in the given format.
+func NewDecimalQuantity(b inf.Dec, format Format) *Quantity {
+ return &Quantity{
+ d: infDecAmount{&b},
+ Format: format,
+ }
+}
+
+// NewQuantity returns a new Quantity representing the given
+// value in the given format.
+func NewQuantity(value int64, format Format) *Quantity {
+ return &Quantity{
+ i: int64Amount{value: value},
+ Format: format,
+ }
+}
+
+// NewMilliQuantity returns a new Quantity representing the given
+// value * 1/1000 in the given format. Note that BinarySI formatting
+// will round fractional values, and will be changed to DecimalSI for
+// values x where (-1 < x < 1) && (x != 0).
+func NewMilliQuantity(value int64, format Format) *Quantity {
+ return &Quantity{
+ i: int64Amount{value: value, scale: -3},
+ Format: format,
+ }
+}
+
+// NewScaledQuantity returns a new Quantity representing the given
+// value * 10^scale in DecimalSI format.
+func NewScaledQuantity(value int64, scale Scale) *Quantity {
+ return &Quantity{
+ i: int64Amount{value: value, scale: scale},
+ Format: DecimalSI,
+ }
+}
+
+// Value returns the unscaled value of q rounded up to the nearest integer away from 0.
+func (q *Quantity) Value() int64 {
+ return q.ScaledValue(0)
+}
+
+// MilliValue returns the value of ceil(q * 1000); this could overflow an int64;
+// if that's a concern, call Value() first to verify the number is small enough.
+func (q *Quantity) MilliValue() int64 {
+ return q.ScaledValue(Milli)
+}
+
+// ScaledValue returns the value of ceil(q / 10^scale).
+// For example, NewQuantity(1, DecimalSI).ScaledValue(Milli) returns 1000.
+// This could overflow an int64.
+// To detect overflow, call Value() first and verify the expected magnitude.
+func (q *Quantity) ScaledValue(scale Scale) int64 {
+ if q.d.Dec == nil {
+ i, _ := q.i.AsScaledInt64(scale)
+ return i
+ }
+ dec := q.d.Dec
+ return scaledValue(dec.UnscaledBig(), int(dec.Scale()), int(scale.infScale()))
+}
+
+// Set sets q's value to be value.
+func (q *Quantity) Set(value int64) {
+ q.SetScaled(value, 0)
+}
+
+// SetMilli sets q's value to be value * 1/1000.
+func (q *Quantity) SetMilli(value int64) {
+ q.SetScaled(value, Milli)
+}
+
+// SetScaled sets q's value to be value * 10^scale
+func (q *Quantity) SetScaled(value int64, scale Scale) {
+ q.s = ""
+ q.d.Dec = nil
+ q.i = int64Amount{value: value, scale: scale}
+}
diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/scale_int.go b/pkg/k8s.io/apimachinery/pkg/api/resource/scale_int.go
new file mode 100644
index 000000000..55e177b0e
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/pkg/api/resource/scale_int.go
@@ -0,0 +1,95 @@
+/*
+Copyright 2015 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package resource
+
+import (
+ "math"
+ "math/big"
+ "sync"
+)
+
+var (
+ // A sync pool to reduce allocation.
+ intPool sync.Pool
+ maxInt64 = big.NewInt(math.MaxInt64)
+)
+
+func init() {
+ intPool.New = func() interface{} {
+ return &big.Int{}
+ }
+}
+
+// scaledValue scales given unscaled value from scale to new Scale and returns
+// an int64. It ALWAYS rounds up the result when scale down. The final result might
+// overflow.
+//
+// scale, newScale represents the scale of the unscaled decimal.
+// The mathematical value of the decimal is unscaled * 10**(-scale).
+func scaledValue(unscaled *big.Int, scale, newScale int) int64 {
+ dif := scale - newScale
+ if dif == 0 {
+ return unscaled.Int64()
+ }
+
+ // Handle scale up
+ // This is an easy case, we do not need to care about rounding and overflow.
+ // If any intermediate operation causes overflow, the result will overflow.
+ if dif < 0 {
+ return unscaled.Int64() * int64(math.Pow10(-dif))
+ }
+
+ // Handle scale down
+ // We have to be careful about the intermediate operations.
+
+ // fast path when unscaled < max.Int64 and exp(10,dif) < max.Int64
+ const log10MaxInt64 = 19
+ if unscaled.Cmp(maxInt64) < 0 && dif < log10MaxInt64 {
+ divide := int64(math.Pow10(dif))
+ result := unscaled.Int64() / divide
+ mod := unscaled.Int64() % divide
+ if mod != 0 {
+ return result + 1
+ }
+ return result
+ }
+
+ // We should only convert back to int64 when getting the result.
+ divisor := intPool.Get().(*big.Int)
+ exp := intPool.Get().(*big.Int)
+ result := intPool.Get().(*big.Int)
+ defer func() {
+ intPool.Put(divisor)
+ intPool.Put(exp)
+ intPool.Put(result)
+ }()
+
+ // divisor = 10^(dif)
+ // TODO: create loop up table if exp costs too much.
+ divisor.Exp(bigTen, exp.SetInt64(int64(dif)), nil)
+ // reuse exp
+ remainder := exp
+
+ // result = unscaled / divisor
+ // remainder = unscaled % divisor
+ result.DivMod(unscaled, divisor, remainder)
+ if remainder.Sign() != 0 {
+ return result.Int64() + 1
+ }
+
+ return result.Int64()
+}
diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/suffix.go b/pkg/k8s.io/apimachinery/pkg/api/resource/suffix.go
new file mode 100644
index 000000000..6ec527f9c
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/pkg/api/resource/suffix.go
@@ -0,0 +1,198 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package resource
+
+import (
+ "strconv"
+)
+
+type suffix string
+
+// suffixer can interpret and construct suffixes.
+type suffixer interface {
+ interpret(suffix) (base, exponent int32, fmt Format, ok bool)
+ construct(base, exponent int32, fmt Format) (s suffix, ok bool)
+ constructBytes(base, exponent int32, fmt Format) (s []byte, ok bool)
+}
+
+// quantitySuffixer handles suffixes for all three formats that quantity
+// can handle.
+var quantitySuffixer = newSuffixer()
+
+type bePair struct {
+ base, exponent int32
+}
+
+type listSuffixer struct {
+ suffixToBE map[suffix]bePair
+ beToSuffix map[bePair]suffix
+ beToSuffixBytes map[bePair][]byte
+}
+
+func (ls *listSuffixer) addSuffix(s suffix, pair bePair) {
+ if ls.suffixToBE == nil {
+ ls.suffixToBE = map[suffix]bePair{}
+ }
+ if ls.beToSuffix == nil {
+ ls.beToSuffix = map[bePair]suffix{}
+ }
+ if ls.beToSuffixBytes == nil {
+ ls.beToSuffixBytes = map[bePair][]byte{}
+ }
+ ls.suffixToBE[s] = pair
+ ls.beToSuffix[pair] = s
+ ls.beToSuffixBytes[pair] = []byte(s)
+}
+
+func (ls *listSuffixer) lookup(s suffix) (base, exponent int32, ok bool) {
+ pair, ok := ls.suffixToBE[s]
+ if !ok {
+ return 0, 0, false
+ }
+ return pair.base, pair.exponent, true
+}
+
+func (ls *listSuffixer) construct(base, exponent int32) (s suffix, ok bool) {
+ s, ok = ls.beToSuffix[bePair{base, exponent}]
+ return
+}
+
+func (ls *listSuffixer) constructBytes(base, exponent int32) (s []byte, ok bool) {
+ s, ok = ls.beToSuffixBytes[bePair{base, exponent}]
+ return
+}
+
+type suffixHandler struct {
+ decSuffixes listSuffixer
+ binSuffixes listSuffixer
+}
+
+type fastLookup struct {
+ *suffixHandler
+}
+
+func (l fastLookup) interpret(s suffix) (base, exponent int32, format Format, ok bool) {
+ switch s {
+ case "":
+ return 10, 0, DecimalSI, true
+ case "n":
+ return 10, -9, DecimalSI, true
+ case "u":
+ return 10, -6, DecimalSI, true
+ case "m":
+ return 10, -3, DecimalSI, true
+ case "k":
+ return 10, 3, DecimalSI, true
+ case "M":
+ return 10, 6, DecimalSI, true
+ case "G":
+ return 10, 9, DecimalSI, true
+ }
+ return l.suffixHandler.interpret(s)
+}
+
+func newSuffixer() suffixer {
+ sh := &suffixHandler{}
+
+ // IMPORTANT: if you change this section you must change fastLookup
+
+ sh.binSuffixes.addSuffix("Ki", bePair{2, 10})
+ sh.binSuffixes.addSuffix("Mi", bePair{2, 20})
+ sh.binSuffixes.addSuffix("Gi", bePair{2, 30})
+ sh.binSuffixes.addSuffix("Ti", bePair{2, 40})
+ sh.binSuffixes.addSuffix("Pi", bePair{2, 50})
+ sh.binSuffixes.addSuffix("Ei", bePair{2, 60})
+ // Don't emit an error when trying to produce
+ // a suffix for 2^0.
+ sh.decSuffixes.addSuffix("", bePair{2, 0})
+
+ sh.decSuffixes.addSuffix("n", bePair{10, -9})
+ sh.decSuffixes.addSuffix("u", bePair{10, -6})
+ sh.decSuffixes.addSuffix("m", bePair{10, -3})
+ sh.decSuffixes.addSuffix("", bePair{10, 0})
+ sh.decSuffixes.addSuffix("k", bePair{10, 3})
+ sh.decSuffixes.addSuffix("M", bePair{10, 6})
+ sh.decSuffixes.addSuffix("G", bePair{10, 9})
+ sh.decSuffixes.addSuffix("T", bePair{10, 12})
+ sh.decSuffixes.addSuffix("P", bePair{10, 15})
+ sh.decSuffixes.addSuffix("E", bePair{10, 18})
+
+ return fastLookup{sh}
+}
+
+func (sh *suffixHandler) construct(base, exponent int32, fmt Format) (s suffix, ok bool) {
+ switch fmt {
+ case DecimalSI:
+ return sh.decSuffixes.construct(base, exponent)
+ case BinarySI:
+ return sh.binSuffixes.construct(base, exponent)
+ case DecimalExponent:
+ if base != 10 {
+ return "", false
+ }
+ if exponent == 0 {
+ return "", true
+ }
+ return suffix("e" + strconv.FormatInt(int64(exponent), 10)), true
+ }
+ return "", false
+}
+
+func (sh *suffixHandler) constructBytes(base, exponent int32, format Format) (s []byte, ok bool) {
+ switch format {
+ case DecimalSI:
+ return sh.decSuffixes.constructBytes(base, exponent)
+ case BinarySI:
+ return sh.binSuffixes.constructBytes(base, exponent)
+ case DecimalExponent:
+ if base != 10 {
+ return nil, false
+ }
+ if exponent == 0 {
+ return nil, true
+ }
+ result := make([]byte, 8)
+ result[0] = 'e'
+ number := strconv.AppendInt(result[1:1], int64(exponent), 10)
+ if &result[1] == &number[0] {
+ return result[:1+len(number)], true
+ }
+ result = append(result[:1], number...)
+ return result, true
+ }
+ return nil, false
+}
+
+func (sh *suffixHandler) interpret(suffix suffix) (base, exponent int32, fmt Format, ok bool) {
+ // Try lookup tables first
+ if b, e, ok := sh.decSuffixes.lookup(suffix); ok {
+ return b, e, DecimalSI, true
+ }
+ if b, e, ok := sh.binSuffixes.lookup(suffix); ok {
+ return b, e, BinarySI, true
+ }
+
+ if len(suffix) > 1 && (suffix[0] == 'E' || suffix[0] == 'e') {
+ parsed, err := strconv.ParseInt(string(suffix[1:]), 10, 64)
+ if err != nil {
+ return 0, 0, DecimalExponent, false
+ }
+ return 10, int32(parsed), DecimalExponent, true
+ }
+
+ return 0, 0, DecimalExponent, false
+}
diff --git a/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go b/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go
new file mode 100644
index 000000000..f95ba6eac
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go
@@ -0,0 +1,55 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1
+
+import (
+ "encoding/json"
+ "time"
+)
+
+// Duration is a wrapper around time.Duration which supports correct
+// marshaling to YAML and JSON. In particular, it marshals into strings, which
+// can be used as map keys in json.
+type Duration struct {
+ time.Duration
+}
+
+// UnmarshalJSON implements the json.Unmarshaller interface.
+func (d *Duration) UnmarshalJSON(b []byte) error {
+ var str string
+ err := json.Unmarshal(b, &str)
+ if err != nil {
+ return err
+ }
+
+ pd, err := time.ParseDuration(str)
+ if err != nil {
+ return err
+ }
+ d.Duration = pd
+ return nil
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (d Duration) MarshalJSON() ([]byte, error) {
+ return json.Marshal(d.Duration.String())
+}
+
+// ToUnstructured implements the value.UnstructuredConverter interface.
+func (d Duration) ToUnstructured() interface{} {
+ return d.Duration.String()
+}
diff --git a/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time.go b/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time.go
new file mode 100644
index 000000000..a6dbd7cbd
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time.go
@@ -0,0 +1,171 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1
+
+import (
+ "encoding/json"
+ "time"
+)
+
+const RFC3339Micro = "2006-01-02T15:04:05.000000Z07:00"
+
+// MicroTime is version of Time with microsecond level precision.
+//
+// +protobuf.options.marshal=false
+// +protobuf.as=Timestamp
+// +protobuf.options.(gogoproto.goproto_stringer)=false
+type MicroTime struct {
+ time.Time
+}
+
+// DeepCopy returns a deep-copy of the MicroTime value. The underlying time.Time
+// type is effectively immutable in the time API, so it is safe to
+// copy-by-assign, despite the presence of (unexported) Pointer fields.
+func (t *MicroTime) DeepCopyInto(out *MicroTime) {
+ *out = *t
+}
+
+// NewMicroTime returns a wrapped instance of the provided time
+func NewMicroTime(time time.Time) MicroTime {
+ return MicroTime{time}
+}
+
+// DateMicro returns the MicroTime corresponding to the supplied parameters
+// by wrapping time.Date.
+func DateMicro(year int, month time.Month, day, hour, min, sec, nsec int, loc *time.Location) MicroTime {
+ return MicroTime{time.Date(year, month, day, hour, min, sec, nsec, loc)}
+}
+
+// NowMicro returns the current local time.
+func NowMicro() MicroTime {
+ return MicroTime{time.Now()}
+}
+
+// IsZero returns true if the value is nil or time is zero.
+func (t *MicroTime) IsZero() bool {
+ if t == nil {
+ return true
+ }
+ return t.Time.IsZero()
+}
+
+// Before reports whether the time instant t is before u.
+func (t *MicroTime) Before(u *MicroTime) bool {
+ if t != nil && u != nil {
+ return t.Time.Before(u.Time)
+ }
+ return false
+}
+
+// Equal reports whether the time instant t is equal to u.
+func (t *MicroTime) Equal(u *MicroTime) bool {
+ if t == nil && u == nil {
+ return true
+ }
+ if t != nil && u != nil {
+ return t.Time.Equal(u.Time)
+ }
+ return false
+}
+
+// BeforeTime reports whether the time instant t is before second-lever precision u.
+func (t *MicroTime) BeforeTime(u *Time) bool {
+ if t != nil && u != nil {
+ return t.Time.Before(u.Time)
+ }
+ return false
+}
+
+// EqualTime reports whether the time instant t is equal to second-lever precision u.
+func (t *MicroTime) EqualTime(u *Time) bool {
+ if t == nil && u == nil {
+ return true
+ }
+ if t != nil && u != nil {
+ return t.Time.Equal(u.Time)
+ }
+ return false
+}
+
+// UnixMicro returns the local time corresponding to the given Unix time
+// by wrapping time.Unix.
+func UnixMicro(sec int64, nsec int64) MicroTime {
+ return MicroTime{time.Unix(sec, nsec)}
+}
+
+// UnmarshalJSON implements the json.Unmarshaller interface.
+func (t *MicroTime) UnmarshalJSON(b []byte) error {
+ if len(b) == 4 && string(b) == "null" {
+ t.Time = time.Time{}
+ return nil
+ }
+
+ var str string
+ err := json.Unmarshal(b, &str)
+ if err != nil {
+ return err
+ }
+
+ pt, err := time.Parse(RFC3339Micro, str)
+ if err != nil {
+ return err
+ }
+
+ t.Time = pt.Local()
+ return nil
+}
+
+// UnmarshalQueryParameter converts from a URL query parameter value to an object
+func (t *MicroTime) UnmarshalQueryParameter(str string) error {
+ if len(str) == 0 {
+ t.Time = time.Time{}
+ return nil
+ }
+ // Tolerate requests from older clients that used JSON serialization to build query params
+ if len(str) == 4 && str == "null" {
+ t.Time = time.Time{}
+ return nil
+ }
+
+ pt, err := time.Parse(RFC3339Micro, str)
+ if err != nil {
+ return err
+ }
+
+ t.Time = pt.Local()
+ return nil
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (t MicroTime) MarshalJSON() ([]byte, error) {
+ if t.IsZero() {
+ // Encode unset/nil objects as JSON's "null".
+ return []byte("null"), nil
+ }
+
+ return json.Marshal(t.UTC().Format(RFC3339Micro))
+}
+
+// MarshalQueryParameter converts to a URL query parameter value
+func (t MicroTime) MarshalQueryParameter() (string, error) {
+ if t.IsZero() {
+ // Encode unset/nil objects as an empty string
+ return "", nil
+ }
+
+ return t.UTC().Format(RFC3339Micro), nil
+}
diff --git a/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/time.go b/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/time.go
new file mode 100644
index 000000000..bdc55ab34
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/time.go
@@ -0,0 +1,172 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1
+
+import (
+ "encoding/json"
+ "time"
+)
+
+// Time is a wrapper around time.Time which supports correct
+// marshaling to YAML and JSON. Wrappers are provided for many
+// of the factory methods that the time package offers.
+//
+// +protobuf.options.marshal=false
+// +protobuf.as=Timestamp
+// +protobuf.options.(gogoproto.goproto_stringer)=false
+type Time struct {
+ time.Time
+}
+
+// DeepCopyInto creates a deep-copy of the Time value. The underlying time.Time
+// type is effectively immutable in the time API, so it is safe to
+// copy-by-assign, despite the presence of (unexported) Pointer fields.
+func (t *Time) DeepCopyInto(out *Time) {
+ *out = *t
+}
+
+// NewTime returns a wrapped instance of the provided time
+func NewTime(time time.Time) Time {
+ return Time{time}
+}
+
+// Date returns the Time corresponding to the supplied parameters
+// by wrapping time.Date.
+func Date(year int, month time.Month, day, hour, min, sec, nsec int, loc *time.Location) Time {
+ return Time{time.Date(year, month, day, hour, min, sec, nsec, loc)}
+}
+
+// Now returns the current local time.
+func Now() Time {
+ return Time{time.Now()}
+}
+
+// IsZero returns true if the value is nil or time is zero.
+func (t *Time) IsZero() bool {
+ if t == nil {
+ return true
+ }
+ return t.Time.IsZero()
+}
+
+// Before reports whether the time instant t is before u.
+func (t *Time) Before(u *Time) bool {
+ if t != nil && u != nil {
+ return t.Time.Before(u.Time)
+ }
+ return false
+}
+
+// Equal reports whether the time instant t is equal to u.
+func (t *Time) Equal(u *Time) bool {
+ if t == nil && u == nil {
+ return true
+ }
+ if t != nil && u != nil {
+ return t.Time.Equal(u.Time)
+ }
+ return false
+}
+
+// Unix returns the local time corresponding to the given Unix time
+// by wrapping time.Unix.
+func Unix(sec int64, nsec int64) Time {
+ return Time{time.Unix(sec, nsec)}
+}
+
+// Rfc3339Copy returns a copy of the Time at second-level precision.
+func (t Time) Rfc3339Copy() Time {
+ copied, _ := time.Parse(time.RFC3339, t.Format(time.RFC3339))
+ return Time{copied}
+}
+
+// UnmarshalJSON implements the json.Unmarshaller interface.
+func (t *Time) UnmarshalJSON(b []byte) error {
+ if len(b) == 4 && string(b) == "null" {
+ t.Time = time.Time{}
+ return nil
+ }
+
+ var str string
+ err := json.Unmarshal(b, &str)
+ if err != nil {
+ return err
+ }
+
+ pt, err := time.Parse(time.RFC3339, str)
+ if err != nil {
+ return err
+ }
+
+ t.Time = pt.Local()
+ return nil
+}
+
+// UnmarshalQueryParameter converts from a URL query parameter value to an object
+func (t *Time) UnmarshalQueryParameter(str string) error {
+ if len(str) == 0 {
+ t.Time = time.Time{}
+ return nil
+ }
+ // Tolerate requests from older clients that used JSON serialization to build query params
+ if len(str) == 4 && str == "null" {
+ t.Time = time.Time{}
+ return nil
+ }
+
+ pt, err := time.Parse(time.RFC3339, str)
+ if err != nil {
+ return err
+ }
+
+ t.Time = pt.Local()
+ return nil
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (t Time) MarshalJSON() ([]byte, error) {
+ if t.IsZero() {
+ // Encode unset/nil objects as JSON's "null".
+ return []byte("null"), nil
+ }
+ buf := make([]byte, 0, len(time.RFC3339)+2)
+ buf = append(buf, '"')
+ // time cannot contain non escapable JSON characters
+ buf = t.UTC().AppendFormat(buf, time.RFC3339)
+ buf = append(buf, '"')
+ return buf, nil
+}
+
+// ToUnstructured implements the value.UnstructuredConverter interface.
+func (t Time) ToUnstructured() interface{} {
+ if t.IsZero() {
+ return nil
+ }
+ buf := make([]byte, 0, len(time.RFC3339))
+ buf = t.UTC().AppendFormat(buf, time.RFC3339)
+ return string(buf)
+}
+
+// MarshalQueryParameter converts to a URL query parameter value
+func (t Time) MarshalQueryParameter() (string, error) {
+ if t.IsZero() {
+ // Encode unset/nil objects as an empty string
+ return "", nil
+ }
+
+ return t.UTC().Format(time.RFC3339), nil
+}
diff --git a/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/types.go b/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/types.go
new file mode 100644
index 000000000..697817774
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/types.go
@@ -0,0 +1,1332 @@
+/*
+Copyright 2015 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package v1 contains API types that are common to all versions.
+//
+// The package contains two categories of types:
+// - external (serialized) types that lack their own version (e.g TypeMeta)
+// - internal (never-serialized) types that are needed by several different
+// api groups, and so live here, to avoid duplication and/or import loops
+// (e.g. LabelSelector).
+// In the future, we will probably move these categories of objects into
+// separate packages.
+package v1
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/types"
+)
+
+// TypeMeta describes an individual object in an API response or request
+// with strings representing the type of the object and its API schema version.
+// Structures that are versioned or persisted should inline TypeMeta.
+//
+// +k8s:deepcopy-gen=false
+type TypeMeta struct {
+ // 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
+ // +optional
+ Kind string `json:"kind,omitempty"`
+
+ // 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
+ // +optional
+ APIVersion string `json:"apiVersion,omitempty"`
+}
+
+// ListMeta describes metadata that synthetic resources must have, including lists and
+// various status objects. A resource may have only one of {ObjectMeta, ListMeta}.
+type ListMeta struct {
+ // selfLink is a URL representing this object.
+ // Populated by the system.
+ // Read-only.
+ //
+ // DEPRECATED
+ // Kubernetes will stop propagating this field in 1.20 release and the field is planned
+ // to be removed in 1.21 release.
+ // +optional
+ SelfLink string `json:"selfLink,omitempty"`
+
+ // 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
+ // +optional
+ ResourceVersion string `json:"resourceVersion,omitempty"`
+
+ // continue may be set if the user set a limit on the number of items returned, and indicates that
+ // the server has more data available. The value is opaque and may be used to issue another request
+ // to the endpoint that served this list to retrieve the next set of available objects. Continuing a
+ // consistent list may not be possible if the server configuration has changed or more than a few
+ // minutes have passed. The resourceVersion field returned when using this continue value will be
+ // identical to the value in the first response, unless you have received this token from an error
+ // message.
+ Continue string `json:"continue,omitempty"`
+
+ // 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.
+ // +optional
+ RemainingItemCount *int64 `json:"remainingItemCount,omitempty"`
+}
+
+// Field path constants that are specific to the internal API
+// representation.
+const (
+ ObjectNameField = "metadata.name"
+)
+
+// These are internal finalizer values for Kubernetes-like APIs, must be qualified name unless defined here
+const (
+ FinalizerOrphanDependents = "orphan"
+ FinalizerDeleteDependents = "foregroundDeletion"
+)
+
+// ObjectMeta is metadata that all persisted resources must have, which includes all objects
+// users must create.
+type ObjectMeta struct {
+ // Name must be unique within a namespace. Is required when creating resources, although
+ // some resources may allow a client to request the generation of an appropriate name
+ // automatically. Name is primarily intended for creation idempotence and configuration
+ // definition.
+ // Cannot be updated.
+ // More info: http://kubernetes.io/docs/user-guide/identifiers#names
+ // +optional
+ Name string `json:"name,omitempty"`
+
+ // GenerateName is an optional prefix, used by the server, to generate a unique
+ // name ONLY IF the Name field has not been provided.
+ // If this field is used, the name returned to the client will be different
+ // than the name passed. This value will also be combined with a unique suffix.
+ // The provided value has the same validation rules as the Name field,
+ // and may be truncated by the length of the suffix required to make the value
+ // unique on the server.
+ //
+ // If this field is specified and the generated name exists, the server will
+ // NOT return a 409 - instead, it will either return 201 Created or 500 with Reason
+ // ServerTimeout indicating a unique name could not be found in the time allotted, and the client
+ // should retry (optionally after the time indicated in the Retry-After header).
+ //
+ // Applied only if Name is not specified.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency
+ // +optional
+ GenerateName string `json:"generateName,omitempty"`
+
+ // Namespace defines the space within which each name must be unique. An empty namespace is
+ // equivalent to the "default" namespace, but "default" is the canonical representation.
+ // Not all objects are required to be scoped to a namespace - the value of this field for
+ // those objects will be empty.
+ //
+ // Must be a DNS_LABEL.
+ // Cannot be updated.
+ // More info: http://kubernetes.io/docs/user-guide/namespaces
+ // +optional
+ Namespace string `json:"namespace,omitempty"`
+
+ // SelfLink is a URL representing this object.
+ // Populated by the system.
+ // Read-only.
+ //
+ // DEPRECATED
+ // Kubernetes will stop propagating this field in 1.20 release and the field is planned
+ // to be removed in 1.21 release.
+ // +optional
+ SelfLink string `json:"selfLink,omitempty"`
+
+ // UID is the unique in time and space value for this object. It is typically generated by
+ // the server on successful creation of a resource and is not allowed to change on PUT
+ // operations.
+ //
+ // Populated by the system.
+ // Read-only.
+ // More info: http://kubernetes.io/docs/user-guide/identifiers#uids
+ // +optional
+ UID types.UID `json:"uid,omitempty"`
+
+ // An opaque value that represents the internal version of this object that can
+ // be used by clients to determine when objects have changed. May be used for optimistic
+ // concurrency, change detection, and the watch operation on a resource or set of resources.
+ // Clients must treat these values as opaque and passed unmodified back to the server.
+ // They may only be valid for a particular resource or set of resources.
+ //
+ // Populated by the system.
+ // Read-only.
+ // Value must be treated as opaque by clients and .
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
+ // +optional
+ ResourceVersion string `json:"resourceVersion,omitempty"`
+
+ // A sequence number representing a specific generation of the desired state.
+ // Populated by the system. Read-only.
+ // +optional
+ Generation int64 `json:"generation,omitempty"`
+
+ // CreationTimestamp is a timestamp representing the server time when this object was
+ // created. It is not guaranteed to be set in happens-before order across separate operations.
+ // Clients may not set this value. It is represented in RFC3339 form and is in UTC.
+ //
+ // Populated by the system.
+ // Read-only.
+ // Null for lists.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ CreationTimestamp Time `json:"creationTimestamp,omitempty"`
+
+ // DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This
+ // field is set by the server when a graceful deletion is requested by the user, and is not
+ // directly settable by a client. The resource is expected to be deleted (no longer visible
+ // from resource lists, and not reachable by name) after the time in this field, once the
+ // finalizers list is empty. As long as the finalizers list contains items, deletion is blocked.
+ // Once the deletionTimestamp is set, this value may not be unset or be set further into the
+ // future, although it may be shortened or the resource may be deleted prior to this time.
+ // For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react
+ // by sending a graceful termination signal to the containers in the pod. After that 30 seconds,
+ // the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup,
+ // remove the pod from the API. In the presence of network partitions, this object may still
+ // exist after this timestamp, until an administrator or automated process can determine the
+ // resource is fully terminated.
+ // If not set, graceful deletion of the object has not been requested.
+ //
+ // Populated by the system when a graceful deletion is requested.
+ // Read-only.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ DeletionTimestamp *Time `json:"deletionTimestamp,omitempty"`
+
+ // Number of seconds allowed for this object to gracefully terminate before
+ // it will be removed from the system. Only set when deletionTimestamp is also set.
+ // May only be shortened.
+ // Read-only.
+ // +optional
+ DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"`
+
+ // Map of string keys and values that can be used to organize and categorize
+ // (scope and select) objects. May match selectors of replication controllers
+ // and services.
+ // More info: http://kubernetes.io/docs/user-guide/labels
+ // +optional
+ Labels map[string]string `json:"labels,omitempty"`
+
+ // Annotations is an unstructured key value map stored with a resource that may be
+ // set by external tools to store and retrieve arbitrary metadata. They are not
+ // queryable and should be preserved when modifying objects.
+ // More info: http://kubernetes.io/docs/user-guide/annotations
+ // +optional
+ Annotations map[string]string `json:"annotations,omitempty"`
+
+ // List of objects depended by this object. If ALL objects in the list have
+ // been deleted, this object will be garbage collected. If this object is managed by a controller,
+ // then an entry in this list will point to this controller, with the controller field set to true.
+ // There cannot be more than one managing controller.
+ // +optional
+ // +patchMergeKey=uid
+ // +patchStrategy=merge
+ OwnerReferences []OwnerReference `json:"ownerReferences,omitempty" patchStrategy:"merge" patchMergeKey:"uid"`
+
+ // Must be empty before the object is deleted from the registry. Each entry
+ // is an identifier for the responsible component that will remove the entry
+ // from the list. If the deletionTimestamp of the object is non-nil, entries
+ // in this list can only be removed.
+ // Finalizers may be processed and removed in any order. Order is NOT enforced
+ // because it introduces significant risk of stuck finalizers.
+ // finalizers is a shared field, any actor with permission can reorder it.
+ // If the finalizer list is processed in order, then this can lead to a situation
+ // in which the component responsible for the first finalizer in the list is
+ // waiting for a signal (field value, external system, or other) produced by a
+ // component responsible for a finalizer later in the list, resulting in a deadlock.
+ // Without enforced ordering finalizers are free to order amongst themselves and
+ // are not vulnerable to ordering changes in the list.
+ // +optional
+ // +patchStrategy=merge
+ Finalizers []string `json:"finalizers,omitempty" patchStrategy:"merge"`
+
+ // The name of the cluster which the object belongs to.
+ // This is used to distinguish resources with same name and namespace in different clusters.
+ // This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.
+ // +optional
+ ClusterName string `json:"clusterName,omitempty"`
+
+ // ManagedFields maps workflow-id and version to the set of fields
+ // that are managed by that workflow. This is mostly for internal
+ // housekeeping, and users typically shouldn't need to set or
+ // understand this field. A workflow can be the user's name, a
+ // controller's name, or the name of a specific apply path like
+ // "ci-cd". The set of fields is always in the version that the
+ // workflow used when modifying the object.
+ //
+ // +optional
+ ManagedFields []ManagedFieldsEntry `json:"managedFields,omitempty"`
+}
+
+const (
+ // NamespaceDefault means the object is in the default namespace which is applied when not specified by clients
+ NamespaceDefault = "default"
+ // NamespaceAll is the default argument to specify on a context when you want to list or filter resources across all namespaces
+ NamespaceAll = ""
+ // NamespaceNone is the argument for a context when there is no namespace.
+ NamespaceNone = ""
+ // NamespaceSystem is the system namespace where we place system components.
+ NamespaceSystem = "kube-system"
+ // NamespacePublic is the namespace where we place public info (ConfigMaps)
+ NamespacePublic = "kube-public"
+)
+
+// OwnerReference contains enough information to let you identify an owning
+// object. An owning object must be in the same namespace as the dependent, or
+// be cluster-scoped, so there is no namespace field.
+// +structType=atomic
+type OwnerReference struct {
+ // API version of the referent.
+ APIVersion string `json:"apiVersion"`
+ // Kind of the referent.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ Kind string `json:"kind"`
+ // Name of the referent.
+ // More info: http://kubernetes.io/docs/user-guide/identifiers#names
+ Name string `json:"name"`
+ // UID of the referent.
+ // More info: http://kubernetes.io/docs/user-guide/identifiers#uids
+ UID types.UID `json:"uid"`
+ // If true, this reference points to the managing controller.
+ // +optional
+ Controller *bool `json:"controller,omitempty"`
+ // If true, AND if the owner has the "foregroundDeletion" finalizer, then
+ // the owner cannot be deleted from the key-value store until this
+ // reference is removed.
+ // Defaults to false.
+ // To set this field, a user needs "delete" permission of the owner,
+ // otherwise 422 (Unprocessable Entity) will be returned.
+ // +optional
+ BlockOwnerDeletion *bool `json:"blockOwnerDeletion,omitempty"`
+}
+
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ListOptions is the query options to a standard REST list call.
+type ListOptions struct {
+ TypeMeta `json:",inline"`
+
+ // A selector to restrict the list of returned objects by their labels.
+ // Defaults to everything.
+ // +optional
+ LabelSelector string `json:"labelSelector,omitempty"`
+ // A selector to restrict the list of returned objects by their fields.
+ // Defaults to everything.
+ // +optional
+ FieldSelector string `json:"fieldSelector,omitempty"`
+
+ // +k8s:deprecated=includeUninitialized,protobuf=6
+
+ // Watch for changes to the described resources and return them as a stream of
+ // add, update, and remove notifications. Specify resourceVersion.
+ // +optional
+ Watch bool `json:"watch,omitempty"`
+ // allowWatchBookmarks requests watch events with type "BOOKMARK".
+ // Servers that do not implement bookmarks may ignore this flag and
+ // bookmarks are sent at the server's discretion. Clients should not
+ // assume bookmarks are returned at any specific interval, nor may they
+ // assume the server will send any BOOKMARK event during a session.
+ // If this is not a watch, this field is ignored.
+ // +optional
+ AllowWatchBookmarks bool `json:"allowWatchBookmarks,omitempty"`
+
+ // 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
+ // +optional
+ ResourceVersion string `json:"resourceVersion,omitempty"`
+
+ // 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
+ // +optional
+ ResourceVersionMatch ResourceVersionMatch `json:"resourceVersionMatch,omitempty"`
+ // Timeout for the list/watch call.
+ // This limits the duration of the call, regardless of any activity or inactivity.
+ // +optional
+ TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty"`
+
+ // limit is a maximum number of responses to return for a list call. If more items exist, the
+ // server will set the `continue` field on the list metadata to a value that can be used with the
+ // same initial query to retrieve the next set of results. Setting a limit may return fewer than
+ // the requested amount of items (up to zero items) in the event all requested objects are
+ // filtered out and clients should only use the presence of the continue field to determine whether
+ // more results are available. Servers may choose not to support the limit argument and will return
+ // all of the available results. If limit is specified and the continue field is empty, clients may
+ // assume that no more results are available. This field is not supported if watch is true.
+ //
+ // The server guarantees that the objects returned when using continue will be identical to issuing
+ // a single list call without a limit - that is, no objects created, modified, or deleted after the
+ // first request is issued will be included in any subsequent continued requests. This is sometimes
+ // referred to as a consistent snapshot, and ensures that a client that is using limit to receive
+ // smaller chunks of a very large result can ensure they see all possible objects. If objects are
+ // updated during a chunked list the version of the object that was present at the time the first list
+ // result was calculated is returned.
+ Limit int64 `json:"limit,omitempty"`
+ // The continue option should be set when retrieving more results from the server. Since this value is
+ // server defined, clients may only use the continue value from a previous query result with identical
+ // query parameters (except for the value of continue) and the server may reject a continue value it
+ // does not recognize. If the specified continue value is no longer valid whether due to expiration
+ // (generally five to fifteen minutes) or a configuration change on the server, the server will
+ // respond with a 410 ResourceExpired error together with a continue token. If the client needs a
+ // consistent list, it must restart their list without the continue field. Otherwise, the client may
+ // send another list request with the token received with the 410 error, the server will respond with
+ // a list starting from the next key, but from the latest snapshot, which is inconsistent from the
+ // previous list results - objects that are created, modified, or deleted after the first list request
+ // will be included in the response, as long as their keys are after the "next key".
+ //
+ // This field is not supported when watch is true. Clients may start a watch from the last
+ // resourceVersion value returned by the server and not miss any modifications.
+ Continue string `json:"continue,omitempty"`
+}
+
+// resourceVersionMatch specifies how the resourceVersion parameter is applied. resourceVersionMatch
+// may only be set if resourceVersion is also set.
+//
+// "NotOlderThan" matches data at least as new as the provided resourceVersion.
+// "Exact" matches data at the exact resourceVersion provided.
+//
+// See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for
+// details.
+type ResourceVersionMatch string
+
+const (
+ // ResourceVersionMatchNotOlderThan matches data at least as new as the provided
+ // resourceVersion.
+ ResourceVersionMatchNotOlderThan ResourceVersionMatch = "NotOlderThan"
+ // ResourceVersionMatchExact matches data at the exact resourceVersion
+ // provided.
+ ResourceVersionMatchExact ResourceVersionMatch = "Exact"
+)
+
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// GetOptions is the standard query options to the standard REST get call.
+type GetOptions struct {
+ TypeMeta `json:",inline"`
+ // 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
+ // +optional
+ ResourceVersion string `json:"resourceVersion,omitempty"`
+ // +k8s:deprecated=includeUninitialized,protobuf=2
+}
+
+// DeletionPropagation decides if a deletion will propagate to the dependents of
+// the object, and how the garbage collector will handle the propagation.
+type DeletionPropagation string
+
+const (
+ // Orphans the dependents.
+ DeletePropagationOrphan DeletionPropagation = "Orphan"
+ // Deletes the object from the key-value store, the garbage collector will
+ // delete the dependents in the background.
+ DeletePropagationBackground DeletionPropagation = "Background"
+ // The object exists in the key-value store until the garbage collector
+ // deletes all the dependents whose ownerReference.blockOwnerDeletion=true
+ // from the key-value store. API sever will put the "foregroundDeletion"
+ // finalizer on the object, and sets its deletionTimestamp. This policy is
+ // cascading, i.e., the dependents will be deleted with Foreground.
+ DeletePropagationForeground DeletionPropagation = "Foreground"
+)
+
+const (
+ // DryRunAll means to complete all processing stages, but don't
+ // persist changes to storage.
+ DryRunAll = "All"
+)
+
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// DeleteOptions may be provided when deleting an API object.
+type DeleteOptions struct {
+ TypeMeta `json:",inline"`
+
+ // The duration in seconds before the object should be deleted. Value must be non-negative integer.
+ // The value zero indicates delete immediately. If this value is nil, the default grace period for the
+ // specified type will be used.
+ // Defaults to a per object value if not specified. zero means delete immediately.
+ // +optional
+ GracePeriodSeconds *int64 `json:"gracePeriodSeconds,omitempty"`
+
+ // Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be
+ // returned.
+ // +k8s:conversion-gen=false
+ // +optional
+ Preconditions *Preconditions `json:"preconditions,omitempty"`
+
+ // Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7.
+ // Should the dependent objects be orphaned. If true/false, the "orphan"
+ // finalizer will be added to/removed from the object's finalizers list.
+ // Either this field or PropagationPolicy may be set, but not both.
+ // +optional
+ OrphanDependents *bool `json:"orphanDependents,omitempty"`
+
+ // Whether and how garbage collection will be performed.
+ // Either this field or OrphanDependents may be set, but not both.
+ // The default policy is decided by the existing finalizer set in the
+ // metadata.finalizers and the resource-specific default policy.
+ // Acceptable values are: 'Orphan' - orphan the dependents; 'Background' -
+ // allow the garbage collector to delete the dependents in the background;
+ // 'Foreground' - a cascading policy that deletes all dependents in the
+ // foreground.
+ // +optional
+ PropagationPolicy *DeletionPropagation `json:"propagationPolicy,omitempty"`
+
+ // When present, indicates that modifications should not be
+ // persisted. An invalid or unrecognized dryRun directive will
+ // result in an error response and no further processing of the
+ // request. Valid values are:
+ // - All: all dry run stages will be processed
+ // +optional
+ DryRun []string `json:"dryRun,omitempty"`
+}
+
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// CreateOptions may be provided when creating an API object.
+type CreateOptions struct {
+ TypeMeta `json:",inline"`
+
+ // When present, indicates that modifications should not be
+ // persisted. An invalid or unrecognized dryRun directive will
+ // result in an error response and no further processing of the
+ // request. Valid values are:
+ // - All: all dry run stages will be processed
+ // +optional
+ DryRun []string `json:"dryRun,omitempty"`
+ // +k8s:deprecated=includeUninitialized,protobuf=2
+
+ // fieldManager is a name associated with the actor or entity
+ // that is making these changes. The value must be less than or
+ // 128 characters long, and only contain printable characters,
+ // as defined by https://golang.org/pkg/unicode/#IsPrint.
+ // +optional
+ FieldManager string `json:"fieldManager,omitempty"`
+}
+
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// PatchOptions may be provided when patching an API object.
+// PatchOptions is meant to be a superset of UpdateOptions.
+type PatchOptions struct {
+ TypeMeta `json:",inline"`
+
+ // When present, indicates that modifications should not be
+ // persisted. An invalid or unrecognized dryRun directive will
+ // result in an error response and no further processing of the
+ // request. Valid values are:
+ // - All: all dry run stages will be processed
+ // +optional
+ DryRun []string `json:"dryRun,omitempty"`
+
+ // Force is going to "force" Apply requests. It means user will
+ // re-acquire conflicting fields owned by other people. Force
+ // flag must be unset for non-apply patch requests.
+ // +optional
+ Force *bool `json:"force,omitempty"`
+
+ // fieldManager is a name associated with the actor or entity
+ // that is making these changes. The value must be less than or
+ // 128 characters long, and only contain printable characters,
+ // as defined by https://golang.org/pkg/unicode/#IsPrint. This
+ // field is required for apply requests
+ // (application/apply-patch) but optional for non-apply patch
+ // types (JsonPatch, MergePatch, StrategicMergePatch).
+ // +optional
+ FieldManager string `json:"fieldManager,omitempty"`
+}
+
+// ApplyOptions may be provided when applying an API object.
+// FieldManager is required for apply requests.
+// ApplyOptions is equivalent to PatchOptions. It is provided as a convenience with documentation
+// that speaks specifically to how the options fields relate to apply.
+type ApplyOptions struct {
+ TypeMeta `json:",inline"`
+
+ // When present, indicates that modifications should not be
+ // persisted. An invalid or unrecognized dryRun directive will
+ // result in an error response and no further processing of the
+ // request. Valid values are:
+ // - All: all dry run stages will be processed
+ // +optional
+ DryRun []string `json:"dryRun,omitempty"`
+
+ // Force is going to "force" Apply requests. It means user will
+ // re-acquire conflicting fields owned by other people.
+ Force bool `json:"force"`
+
+ // fieldManager is a name associated with the actor or entity
+ // that is making these changes. The value must be less than or
+ // 128 characters long, and only contain printable characters,
+ // as defined by https://golang.org/pkg/unicode/#IsPrint. This
+ // field is required.
+ FieldManager string `json:"fieldManager"`
+}
+
+func (o ApplyOptions) ToPatchOptions() PatchOptions {
+ return PatchOptions{DryRun: o.DryRun, Force: &o.Force, FieldManager: o.FieldManager}
+}
+
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// UpdateOptions may be provided when updating an API object.
+// All fields in UpdateOptions should also be present in PatchOptions.
+type UpdateOptions struct {
+ TypeMeta `json:",inline"`
+
+ // When present, indicates that modifications should not be
+ // persisted. An invalid or unrecognized dryRun directive will
+ // result in an error response and no further processing of the
+ // request. Valid values are:
+ // - All: all dry run stages will be processed
+ // +optional
+ DryRun []string `json:"dryRun,omitempty"`
+
+ // fieldManager is a name associated with the actor or entity
+ // that is making these changes. The value must be less than or
+ // 128 characters long, and only contain printable characters,
+ // as defined by https://golang.org/pkg/unicode/#IsPrint.
+ // +optional
+ FieldManager string `json:"fieldManager,omitempty"`
+}
+
+// Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.
+type Preconditions struct {
+ // Specifies the target UID.
+ // +optional
+ UID *types.UID `json:"uid,omitempty"`
+ // Specifies the target ResourceVersion
+ // +optional
+ ResourceVersion *string `json:"resourceVersion,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// Status is a return value for calls that don't return other objects.
+type Status struct {
+ TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ ListMeta `json:"metadata,omitempty"`
+
+ // Status of the operation.
+ // One of: "Success" or "Failure".
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
+ // +optional
+ Status string `json:"status,omitempty"`
+ // A human-readable description of the status of this operation.
+ // +optional
+ Message string `json:"message,omitempty"`
+ // A machine-readable description of why this operation is in the
+ // "Failure" status. If this value is empty there
+ // is no information available. A Reason clarifies an HTTP status
+ // code but does not override it.
+ // +optional
+ Reason StatusReason `json:"reason,omitempty"`
+ // Extended data associated with the reason. Each reason may define its
+ // own extended details. This field is optional and the data returned
+ // is not guaranteed to conform to any schema except that defined by
+ // the reason type.
+ // +optional
+ Details *StatusDetails `json:"details,omitempty"`
+ // Suggested HTTP return code for this status, 0 if not set.
+ // +optional
+ Code int32 `json:"code,omitempty"`
+}
+
+// StatusDetails is a set of additional properties that MAY be set by the
+// server to provide additional information about a response. The Reason
+// field of a Status object defines what attributes will be set. Clients
+// must ignore fields that do not match the defined type of each attribute,
+// and should assume that any attribute may be empty, invalid, or under
+// defined.
+type StatusDetails struct {
+ // The name attribute of the resource associated with the status StatusReason
+ // (when there is a single name which can be described).
+ // +optional
+ Name string `json:"name,omitempty"`
+ // The group attribute of the resource associated with the status StatusReason.
+ // +optional
+ Group string `json:"group,omitempty"`
+ // The kind attribute of the resource associated with the status StatusReason.
+ // On some operations may differ from the requested resource Kind.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ Kind string `json:"kind,omitempty"`
+ // UID of the resource.
+ // (when there is a single resource which can be described).
+ // More info: http://kubernetes.io/docs/user-guide/identifiers#uids
+ // +optional
+ UID types.UID `json:"uid,omitempty"`
+ // The Causes array includes more details associated with the StatusReason
+ // failure. Not all StatusReasons may provide detailed causes.
+ // +optional
+ Causes []StatusCause `json:"causes,omitempty"`
+ // If specified, the time in seconds before the operation should be retried. Some errors may indicate
+ // the client must take an alternate action - for those errors this field may indicate how long to wait
+ // before taking the alternate action.
+ // +optional
+ RetryAfterSeconds int32 `json:"retryAfterSeconds,omitempty"`
+}
+
+// Values of Status.Status
+const (
+ StatusSuccess = "Success"
+ StatusFailure = "Failure"
+)
+
+// StatusReason is an enumeration of possible failure causes. Each StatusReason
+// must map to a single HTTP status code, but multiple reasons may map
+// to the same HTTP status code.
+// TODO: move to apiserver
+type StatusReason string
+
+const (
+ // StatusReasonUnknown means the server has declined to indicate a specific reason.
+ // The details field may contain other information about this error.
+ // Status code 500.
+ StatusReasonUnknown StatusReason = ""
+
+ // StatusReasonUnauthorized means the server can be reached and understood the request, but requires
+ // the user to present appropriate authorization credentials (identified by the WWW-Authenticate header)
+ // in order for the action to be completed. If the user has specified credentials on the request, the
+ // server considers them insufficient.
+ // Status code 401
+ StatusReasonUnauthorized StatusReason = "Unauthorized"
+
+ // StatusReasonForbidden means the server can be reached and understood the request, but refuses
+ // to take any further action. It is the result of the server being configured to deny access for some reason
+ // to the requested resource by the client.
+ // Details (optional):
+ // "kind" string - the kind attribute of the forbidden resource
+ // on some operations may differ from the requested
+ // resource.
+ // "id" string - the identifier of the forbidden resource
+ // Status code 403
+ StatusReasonForbidden StatusReason = "Forbidden"
+
+ // StatusReasonNotFound means one or more resources required for this operation
+ // could not be found.
+ // Details (optional):
+ // "kind" string - the kind attribute of the missing resource
+ // on some operations may differ from the requested
+ // resource.
+ // "id" string - the identifier of the missing resource
+ // Status code 404
+ StatusReasonNotFound StatusReason = "NotFound"
+
+ // StatusReasonAlreadyExists means the resource you are creating already exists.
+ // Details (optional):
+ // "kind" string - the kind attribute of the conflicting resource
+ // "id" string - the identifier of the conflicting resource
+ // Status code 409
+ StatusReasonAlreadyExists StatusReason = "AlreadyExists"
+
+ // StatusReasonConflict means the requested operation cannot be completed
+ // due to a conflict in the operation. The client may need to alter the
+ // request. Each resource may define custom details that indicate the
+ // nature of the conflict.
+ // Status code 409
+ StatusReasonConflict StatusReason = "Conflict"
+
+ // StatusReasonGone means the item is no longer available at the server and no
+ // forwarding address is known.
+ // Status code 410
+ StatusReasonGone StatusReason = "Gone"
+
+ // StatusReasonInvalid means the requested create or update operation cannot be
+ // completed due to invalid data provided as part of the request. The client may
+ // need to alter the request. When set, the client may use the StatusDetails
+ // message field as a summary of the issues encountered.
+ // Details (optional):
+ // "kind" string - the kind attribute of the invalid resource
+ // "id" string - the identifier of the invalid resource
+ // "causes" - one or more StatusCause entries indicating the data in the
+ // provided resource that was invalid. The code, message, and
+ // field attributes will be set.
+ // Status code 422
+ StatusReasonInvalid StatusReason = "Invalid"
+
+ // StatusReasonServerTimeout means the server can be reached and understood the request,
+ // but cannot complete the action in a reasonable time. The client should retry the request.
+ // This is may be due to temporary server load or a transient communication issue with
+ // another server. Status code 500 is used because the HTTP spec provides no suitable
+ // server-requested client retry and the 5xx class represents actionable errors.
+ // Details (optional):
+ // "kind" string - the kind attribute of the resource being acted on.
+ // "id" string - the operation that is being attempted.
+ // "retryAfterSeconds" int32 - the number of seconds before the operation should be retried
+ // Status code 500
+ StatusReasonServerTimeout StatusReason = "ServerTimeout"
+
+ // StatusReasonTimeout means that the request could not be completed within the given time.
+ // Clients can get this response only when they specified a timeout param in the request,
+ // or if the server cannot complete the operation within a reasonable amount of time.
+ // The request might succeed with an increased value of timeout param. The client *should*
+ // wait at least the number of seconds specified by the retryAfterSeconds field.
+ // Details (optional):
+ // "retryAfterSeconds" int32 - the number of seconds before the operation should be retried
+ // Status code 504
+ StatusReasonTimeout StatusReason = "Timeout"
+
+ // StatusReasonTooManyRequests means the server experienced too many requests within a
+ // given window and that the client must wait to perform the action again. A client may
+ // always retry the request that led to this error, although the client should wait at least
+ // the number of seconds specified by the retryAfterSeconds field.
+ // Details (optional):
+ // "retryAfterSeconds" int32 - the number of seconds before the operation should be retried
+ // Status code 429
+ StatusReasonTooManyRequests StatusReason = "TooManyRequests"
+
+ // StatusReasonBadRequest means that the request itself was invalid, because the request
+ // doesn't make any sense, for example deleting a read-only object. This is different than
+ // StatusReasonInvalid above which indicates that the API call could possibly succeed, but the
+ // data was invalid. API calls that return BadRequest can never succeed.
+ // Status code 400
+ StatusReasonBadRequest StatusReason = "BadRequest"
+
+ // StatusReasonMethodNotAllowed means that the action the client attempted to perform on the
+ // resource was not supported by the code - for instance, attempting to delete a resource that
+ // can only be created. API calls that return MethodNotAllowed can never succeed.
+ // Status code 405
+ StatusReasonMethodNotAllowed StatusReason = "MethodNotAllowed"
+
+ // StatusReasonNotAcceptable means that the accept types indicated by the client were not acceptable
+ // to the server - for instance, attempting to receive protobuf for a resource that supports only json and yaml.
+ // API calls that return NotAcceptable can never succeed.
+ // Status code 406
+ StatusReasonNotAcceptable StatusReason = "NotAcceptable"
+
+ // StatusReasonRequestEntityTooLarge means that the request entity is too large.
+ // Status code 413
+ StatusReasonRequestEntityTooLarge StatusReason = "RequestEntityTooLarge"
+
+ // StatusReasonUnsupportedMediaType means that the content type sent by the client is not acceptable
+ // to the server - for instance, attempting to send protobuf for a resource that supports only json and yaml.
+ // API calls that return UnsupportedMediaType can never succeed.
+ // Status code 415
+ StatusReasonUnsupportedMediaType StatusReason = "UnsupportedMediaType"
+
+ // StatusReasonInternalError indicates that an internal error occurred, it is unexpected
+ // and the outcome of the call is unknown.
+ // Details (optional):
+ // "causes" - The original error
+ // Status code 500
+ StatusReasonInternalError StatusReason = "InternalError"
+
+ // StatusReasonExpired indicates that the request is invalid because the content you are requesting
+ // has expired and is no longer available. It is typically associated with watches that can't be
+ // serviced.
+ // Status code 410 (gone)
+ StatusReasonExpired StatusReason = "Expired"
+
+ // StatusReasonServiceUnavailable means that the request itself was valid,
+ // but the requested service is unavailable at this time.
+ // Retrying the request after some time might succeed.
+ // Status code 503
+ StatusReasonServiceUnavailable StatusReason = "ServiceUnavailable"
+)
+
+// StatusCause provides more information about an api.Status failure, including
+// cases when multiple errors are encountered.
+type StatusCause struct {
+ // A machine-readable description of the cause of the error. If this value is
+ // empty there is no information available.
+ // +optional
+ Type CauseType `json:"reason,omitempty"`
+ // A human-readable description of the cause of the error. This field may be
+ // presented as-is to a reader.
+ // +optional
+ Message string `json:"message,omitempty"`
+ // The field of the resource that has caused this error, as named by its JSON
+ // serialization. May include dot and postfix notation for nested attributes.
+ // Arrays are zero-indexed. Fields may appear more than once in an array of
+ // causes due to fields having multiple errors.
+ // Optional.
+ //
+ // Examples:
+ // "name" - the field "name" on the current resource
+ // "items[0].name" - the field "name" on the first array entry in "items"
+ // +optional
+ Field string `json:"field,omitempty"`
+}
+
+// CauseType is a machine readable value providing more detail about what
+// occurred in a status response. An operation may have multiple causes for a
+// status (whether Failure or Success).
+type CauseType string
+
+const (
+ // CauseTypeFieldValueNotFound is used to report failure to find a requested value
+ // (e.g. looking up an ID).
+ CauseTypeFieldValueNotFound CauseType = "FieldValueNotFound"
+ // CauseTypeFieldValueRequired is used to report required values that are not
+ // provided (e.g. empty strings, null values, or empty arrays).
+ CauseTypeFieldValueRequired CauseType = "FieldValueRequired"
+ // CauseTypeFieldValueDuplicate is used to report collisions of values that must be
+ // unique (e.g. unique IDs).
+ CauseTypeFieldValueDuplicate CauseType = "FieldValueDuplicate"
+ // CauseTypeFieldValueInvalid is used to report malformed values (e.g. failed regex
+ // match).
+ CauseTypeFieldValueInvalid CauseType = "FieldValueInvalid"
+ // CauseTypeFieldValueNotSupported is used to report valid (as per formatting rules)
+ // values that can not be handled (e.g. an enumerated string).
+ CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported"
+ // CauseTypeUnexpectedServerResponse is used to report when the server responded to the client
+ // without the expected return type. The presence of this cause indicates the error may be
+ // due to an intervening proxy or the server software malfunctioning.
+ CauseTypeUnexpectedServerResponse CauseType = "UnexpectedServerResponse"
+ // FieldManagerConflict is used to report when another client claims to manage this field,
+ // It should only be returned for a request using server-side apply.
+ CauseTypeFieldManagerConflict CauseType = "FieldManagerConflict"
+ // CauseTypeResourceVersionTooLarge is used to report that the requested resource version
+ // is newer than the data observed by the API server, so the request cannot be served.
+ CauseTypeResourceVersionTooLarge CauseType = "ResourceVersionTooLarge"
+)
+
+// APIVersions lists the versions that are available, to allow clients to
+// discover the API at /api, which is the root path of the legacy v1 API.
+//
+// +protobuf.options.(gogoproto.goproto_stringer)=false
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type APIVersions struct {
+ TypeMeta `json:",inline"`
+ // versions are the api versions that are available.
+ Versions []string `json:"versions"`
+ // a map of client CIDR to server address that is serving this group.
+ // This is to help clients reach servers in the most network-efficient way possible.
+ // Clients can use the appropriate server address as per the CIDR that they match.
+ // In case of multiple matches, clients should use the longest matching CIDR.
+ // The server returns only those CIDRs that it thinks that the client can match.
+ // For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP.
+ // Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.
+ ServerAddressByClientCIDRs []ServerAddressByClientCIDR `json:"serverAddressByClientCIDRs"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// APIGroupList is a list of APIGroup, to allow clients to discover the API at
+// /apis.
+type APIGroupList struct {
+ TypeMeta `json:",inline"`
+ // groups is a list of APIGroup.
+ Groups []APIGroup `json:"groups"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// APIGroup contains the name, the supported versions, and the preferred version
+// of a group.
+type APIGroup struct {
+ TypeMeta `json:",inline"`
+ // name is the name of the group.
+ Name string `json:"name"`
+ // versions are the versions supported in this group.
+ Versions []GroupVersionForDiscovery `json:"versions"`
+ // preferredVersion is the version preferred by the API server, which
+ // probably is the storage version.
+ // +optional
+ PreferredVersion GroupVersionForDiscovery `json:"preferredVersion,omitempty"`
+ // a map of client CIDR to server address that is serving this group.
+ // This is to help clients reach servers in the most network-efficient way possible.
+ // Clients can use the appropriate server address as per the CIDR that they match.
+ // In case of multiple matches, clients should use the longest matching CIDR.
+ // The server returns only those CIDRs that it thinks that the client can match.
+ // For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP.
+ // Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.
+ // +optional
+ ServerAddressByClientCIDRs []ServerAddressByClientCIDR `json:"serverAddressByClientCIDRs,omitempty"`
+}
+
+// ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match.
+type ServerAddressByClientCIDR struct {
+ // The CIDR with which clients can match their IP to figure out the server address that they should use.
+ ClientCIDR string `json:"clientCIDR"`
+ // Address of this server, suitable for a client that matches the above CIDR.
+ // This can be a hostname, hostname:port, IP or IP:port.
+ ServerAddress string `json:"serverAddress"`
+}
+
+// GroupVersion contains the "group/version" and "version" string of a version.
+// It is made a struct to keep extensibility.
+type GroupVersionForDiscovery struct {
+ // groupVersion specifies the API group and version in the form "group/version"
+ GroupVersion string `json:"groupVersion"`
+ // version specifies the version in the form of "version". This is to save
+ // the clients the trouble of splitting the GroupVersion.
+ Version string `json:"version"`
+}
+
+// APIResource specifies the name of a resource and whether it is namespaced.
+type APIResource struct {
+ // name is the plural name of the resource.
+ Name string `json:"name"`
+ // singularName is the singular name of the resource. This allows clients to handle plural and singular opaquely.
+ // The singularName is more correct for reporting status on a single item and both singular and plural are allowed
+ // from the kubectl CLI interface.
+ SingularName string `json:"singularName"`
+ // namespaced indicates if a resource is namespaced or not.
+ Namespaced bool `json:"namespaced"`
+ // group is the preferred group of the resource. Empty implies the group of the containing resource list.
+ // For subresources, this may have a different value, for example: Scale".
+ Group string `json:"group,omitempty"`
+ // version is the preferred version of the resource. Empty implies the version of the containing resource list
+ // For subresources, this may have a different value, for example: v1 (while inside a v1beta1 version of the core resource's group)".
+ Version string `json:"version,omitempty"`
+ // kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')
+ Kind string `json:"kind"`
+ // verbs is a list of supported kube verbs (this includes get, list, watch, create,
+ // update, patch, delete, deletecollection, and proxy)
+ Verbs Verbs `json:"verbs"`
+ // shortNames is a list of suggested short names of the resource.
+ ShortNames []string `json:"shortNames,omitempty"`
+ // categories is a list of the grouped resources this resource belongs to (e.g. 'all')
+ Categories []string `json:"categories,omitempty"`
+ // The hash value of the storage version, the version this resource is
+ // converted to when written to the data store. Value must be treated
+ // as opaque by clients. Only equality comparison on the value is valid.
+ // This is an alpha feature and may change or be removed in the future.
+ // The field is populated by the apiserver only if the
+ // StorageVersionHash feature gate is enabled.
+ // This field will remain optional even if it graduates.
+ // +optional
+ StorageVersionHash string `json:"storageVersionHash,omitempty"`
+}
+
+// Verbs masks the value so protobuf can generate
+//
+// +protobuf.nullable=true
+// +protobuf.options.(gogoproto.goproto_stringer)=false
+type Verbs []string
+
+func (vs Verbs) String() string {
+ return fmt.Sprintf("%v", []string(vs))
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// APIResourceList is a list of APIResource, it is used to expose the name of the
+// resources supported in a specific group and version, and if the resource
+// is namespaced.
+type APIResourceList struct {
+ TypeMeta `json:",inline"`
+ // groupVersion is the group and version this APIResourceList is for.
+ GroupVersion string `json:"groupVersion"`
+ // resources contains the name of the resources and if they are namespaced.
+ APIResources []APIResource `json:"resources"`
+}
+
+// RootPaths lists the paths available at root.
+// For example: "/healthz", "/apis".
+type RootPaths struct {
+ // paths are the paths available at root.
+ Paths []string `json:"paths"`
+}
+
+// TODO: remove me when watch is refactored
+func LabelSelectorQueryParam(version string) string {
+ return "labelSelector"
+}
+
+// TODO: remove me when watch is refactored
+func FieldSelectorQueryParam(version string) string {
+ return "fieldSelector"
+}
+
+// String returns available api versions as a human-friendly version string.
+func (apiVersions APIVersions) String() string {
+ return strings.Join(apiVersions.Versions, ",")
+}
+
+func (apiVersions APIVersions) GoString() string {
+ return apiVersions.String()
+}
+
+// Patch is provided to give a concrete name and type to the Kubernetes PATCH request body.
+type Patch struct{}
+
+// Note:
+// There are two different styles of label selectors used in versioned types:
+// an older style which is represented as just a string in versioned types, and a
+// newer style that is structured. LabelSelector is an internal representation for the
+// latter style.
+
+// A label selector is a label query over a set of resources. The result of matchLabels and
+// matchExpressions are ANDed. An empty label selector matches all objects. A null
+// label selector matches no objects.
+// +structType=atomic
+type LabelSelector struct {
+ // matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ // map is equivalent to an element of matchExpressions, whose key field is "key", the
+ // operator is "In", and the values array contains only "value". The requirements are ANDed.
+ // +optional
+ MatchLabels map[string]string `json:"matchLabels,omitempty"`
+ // matchExpressions is a list of label selector requirements. The requirements are ANDed.
+ // +optional
+ MatchExpressions []LabelSelectorRequirement `json:"matchExpressions,omitempty"`
+}
+
+// A label selector requirement is a selector that contains values, a key, and an operator that
+// relates the key and values.
+type LabelSelectorRequirement struct {
+ // key is the label key that the selector applies to.
+ // +patchMergeKey=key
+ // +patchStrategy=merge
+ Key string `json:"key" patchStrategy:"merge" patchMergeKey:"key"`
+ // operator represents a key's relationship to a set of values.
+ // Valid operators are In, NotIn, Exists and DoesNotExist.
+ Operator LabelSelectorOperator `json:"operator"`
+ // values is an array of string values. If the operator is In or NotIn,
+ // the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ // the values array must be empty. This array is replaced during a strategic
+ // merge patch.
+ // +optional
+ Values []string `json:"values,omitempty"`
+}
+
+// A label selector operator is the set of operators that can be used in a selector requirement.
+type LabelSelectorOperator string
+
+const (
+ LabelSelectorOpIn LabelSelectorOperator = "In"
+ LabelSelectorOpNotIn LabelSelectorOperator = "NotIn"
+ LabelSelectorOpExists LabelSelectorOperator = "Exists"
+ LabelSelectorOpDoesNotExist LabelSelectorOperator = "DoesNotExist"
+)
+
+// ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of the resource
+// that the fieldset applies to.
+type ManagedFieldsEntry struct {
+ // Manager is an identifier of the workflow managing these fields.
+ Manager string `json:"manager,omitempty"`
+ // Operation is the type of operation which lead to this ManagedFieldsEntry being created.
+ // The only valid values for this field are 'Apply' and 'Update'.
+ Operation ManagedFieldsOperationType `json:"operation,omitempty"`
+ // APIVersion defines the version of this resource that this field set
+ // applies to. The format is "group/version" just like the top-level
+ // APIVersion field. It is necessary to track the version of a field
+ // set because it cannot be automatically converted.
+ APIVersion string `json:"apiVersion,omitempty"`
+ // Time is timestamp of when these fields were set. It should always be empty if Operation is 'Apply'
+ // +optional
+ Time *Time `json:"time,omitempty"`
+
+ // Fields is tombstoned to show why 5 is a reserved protobuf tag.
+ //Fields *Fields `json:"fields,omitempty"`
+
+ // FieldsType is the discriminator for the different fields format and version.
+ // There is currently only one possible value: "FieldsV1"
+ FieldsType string `json:"fieldsType,omitempty"`
+ // FieldsV1 holds the first JSON version format as described in the "FieldsV1" type.
+ // +optional
+ FieldsV1 *FieldsV1 `json:"fieldsV1,omitempty"`
+
+ // Subresource is the name of the subresource used to update that object, or
+ // empty string if the object was updated through the main resource. The
+ // value of this field is used to distinguish between managers, even if they
+ // share the same name. For example, a status update will be distinct from a
+ // regular update using the same manager name.
+ // Note that the APIVersion field is not related to the Subresource field and
+ // it always corresponds to the version of the main resource.
+ Subresource string `json:"subresource,omitempty"`
+}
+
+// ManagedFieldsOperationType is the type of operation which lead to a ManagedFieldsEntry being created.
+type ManagedFieldsOperationType string
+
+const (
+ ManagedFieldsOperationApply ManagedFieldsOperationType = "Apply"
+ ManagedFieldsOperationUpdate ManagedFieldsOperationType = "Update"
+)
+
+// FieldsV1 stores a set of fields in a data structure like a Trie, in JSON format.
+//
+// Each key is either a '.' representing the field itself, and will always map to an empty set,
+// or a string representing a sub-field or item. The string will follow one of these four formats:
+// 'f:<name>', where <name> is the name of a field in a struct, or key in a map
+// 'v:<value>', where <value> is the exact json formatted value of a list item
+// 'i:<index>', where <index> is position of a item in a list
+// 'k:<keys>', where <keys> is a map of a list item's key fields to their unique values
+// If a key maps to an empty Fields value, the field that key represents is part of the set.
+//
+// The exact format is defined in sigs.k8s.io/structured-merge-diff
+// +protobuf.options.(gogoproto.goproto_stringer)=false
+type FieldsV1 struct {
+ // Raw is the underlying serialization of this object.
+ Raw []byte `json:"-"`
+}
+
+func (f FieldsV1) String() string {
+ return string(f.Raw)
+}
+
+type ConditionStatus string
+
+// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
+// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
+// can't decide if a resource is in the condition or not. In the future, we could add other
+// intermediate conditions, e.g. ConditionDegraded.
+const (
+ ConditionTrue ConditionStatus = "True"
+ ConditionFalse ConditionStatus = "False"
+ ConditionUnknown ConditionStatus = "Unknown"
+)
+
+// IncludeObjectPolicy controls which portion of the object is returned with a Table.
+type IncludeObjectPolicy string
+
+const (
+ // IncludeNone returns no object.
+ IncludeNone IncludeObjectPolicy = "None"
+ // IncludeMetadata serializes the object containing only its metadata field.
+ IncludeMetadata IncludeObjectPolicy = "Metadata"
+ // IncludeObject contains the full object.
+ IncludeObject IncludeObjectPolicy = "Object"
+)
+
+// TableOptions are used when a Table is requested by the caller.
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type TableOptions struct {
+ TypeMeta `json:",inline"`
+
+ // NoHeaders is only exposed for internal callers. It is not included in our OpenAPI definitions
+ // and may be removed as a field in a future release.
+ NoHeaders bool `json:"-"`
+
+ // includeObject decides whether to include each object along with its columnar information.
+ // Specifying "None" will return no object, specifying "Object" will return the full object contents, and
+ // specifying "Metadata" (the default) will return the object's metadata in the PartialObjectMetadata kind
+ // in version v1beta1 of the meta.k8s.io API group.
+ IncludeObject IncludeObjectPolicy `json:"includeObject,omitempty"`
+}
+
+// PartialObjectMetadata is a generic representation of any object with ObjectMeta. It allows clients
+// to get access to a particular ObjectMeta schema without knowing the details of the version.
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type PartialObjectMetadata struct {
+ TypeMeta `json:",inline"`
+ // Standard object's metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ ObjectMeta `json:"metadata,omitempty"`
+}
+
+// PartialObjectMetadataList contains a list of objects containing only their metadata
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type PartialObjectMetadataList struct {
+ TypeMeta `json:",inline"`
+ // Standard list metadata.
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ // +optional
+ ListMeta `json:"metadata,omitempty"`
+
+ // items contains each of the included items.
+ Items []PartialObjectMetadata `json:"items"`
+}
+
+// Condition contains details for one aspect of the current state of this API Resource.
+// ---
+// This struct is intended for direct use as an array at the field path .status.conditions. For example,
+// type FooStatus struct{
+// // Represents the observations of a foo's current state.
+// // Known .status.conditions.type are: "Available", "Progressing", and "Degraded"
+// // +patchMergeKey=type
+// // +patchStrategy=merge
+// // +listType=map
+// // +listMapKey=type
+// Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
+//
+// // other fields
+// }
+type Condition struct {
+ // type of condition in CamelCase or in foo.example.com/CamelCase.
+ // ---
+ // Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
+ // useful (see .node.status.conditions), the ability to deconflict is important.
+ // The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ // +required
+ // +kubebuilder:validation:Required
+ // +kubebuilder:validation:Pattern=`^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$`
+ // +kubebuilder:validation:MaxLength=316
+ Type string `json:"type"`
+ // status of the condition, one of True, False, Unknown.
+ // +required
+ // +kubebuilder:validation:Required
+ // +kubebuilder:validation:Enum=True;False;Unknown
+ Status ConditionStatus `json:"status"`
+ // observedGeneration represents the .metadata.generation that the condition was set based upon.
+ // For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
+ // with respect to the current state of the instance.
+ // +optional
+ // +kubebuilder:validation:Minimum=0
+ ObservedGeneration int64 `json:"observedGeneration,omitempty"`
+ // lastTransitionTime is the last time the condition transitioned from one status to another.
+ // This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
+ // +required
+ // +kubebuilder:validation:Required
+ // +kubebuilder:validation:Type=string
+ // +kubebuilder:validation:Format=date-time
+ LastTransitionTime Time `json:"lastTransitionTime"`
+ // reason contains a programmatic identifier indicating the reason for the condition's last transition.
+ // Producers of specific condition types may define expected values and meanings for this field,
+ // and whether the values are considered a guaranteed API.
+ // The value should be a CamelCase string.
+ // This field may not be empty.
+ // +required
+ // +kubebuilder:validation:Required
+ // +kubebuilder:validation:MaxLength=1024
+ // +kubebuilder:validation:MinLength=1
+ // +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
+ Reason string `json:"reason"`
+ // message is a human readable message indicating details about the transition.
+ // This may be an empty string.
+ // +required
+ // +kubebuilder:validation:Required
+ // +kubebuilder:validation:MaxLength=32768
+ Message string `json:"message"`
+}
diff --git a/pkg/k8s.io/apimachinery/pkg/types/uid.go b/pkg/k8s.io/apimachinery/pkg/types/uid.go
new file mode 100644
index 000000000..869339222
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/pkg/types/uid.go
@@ -0,0 +1,22 @@
+/*
+Copyright 2015 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package types
+
+// UID is a type that holds unique ID values, including UUIDs. Because we
+// don't ONLY use UUIDs, this is an alias to string. Being a type captures
+// intent and helps make sure that UIDs and names do not get conflated.
+type UID string
diff --git a/pkg/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go b/pkg/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go
new file mode 100644
index 000000000..a502b5adb
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go
@@ -0,0 +1,43 @@
+//go:build !notest
+// +build !notest
+
+/*
+Copyright 2020 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package intstr
+
+import (
+ fuzz "github.com/google/gofuzz"
+)
+
+// Fuzz satisfies fuzz.Interface
+func (intstr *IntOrString) Fuzz(c fuzz.Continue) {
+ if intstr == nil {
+ return
+ }
+ if c.RandBool() {
+ intstr.Type = Int
+ c.Fuzz(&intstr.IntVal)
+ intstr.StrVal = ""
+ } else {
+ intstr.Type = String
+ intstr.IntVal = 0
+ c.Fuzz(&intstr.StrVal)
+ }
+}
+
+// ensure IntOrString implements fuzz.Interface
+var _ fuzz.Interface = &IntOrString{}
diff --git a/pkg/k8s.io/apimachinery/pkg/util/intstr/intstr.go b/pkg/k8s.io/apimachinery/pkg/util/intstr/intstr.go
new file mode 100644
index 000000000..29872c22c
--- /dev/null
+++ b/pkg/k8s.io/apimachinery/pkg/util/intstr/intstr.go
@@ -0,0 +1,113 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package intstr
+
+import (
+ "encoding/json"
+ "fmt"
+ "strconv"
+)
+
+// IntOrString is a type that can hold an int32 or a string. When used in
+// JSON or YAML marshalling and unmarshalling, it produces or consumes the
+// inner type. This allows you to have, for example, a JSON field that can
+// accept a name or number.
+// TODO: Rename to Int32OrString
+//
+// +protobuf=true
+// +protobuf.options.(gogoproto.goproto_stringer)=false
+// +k8s:openapi-gen=true
+type IntOrString struct {
+ Type Type
+ IntVal int32
+ StrVal string
+}
+
+// Type represents the stored type of IntOrString.
+type Type int64
+
+const (
+ Int Type = iota // The IntOrString holds an int.
+ String // The IntOrString holds a string.
+)
+
+// FromInt creates an IntOrString object with an int32 value. It is
+// your responsibility not to call this method with a value greater
+// than int32.
+// TODO: convert to (val int32)
+func FromInt(val int) IntOrString {
+ return IntOrString{Type: Int, IntVal: int32(val)}
+}
+
+// FromString creates an IntOrString object with a string value.
+func FromString(val string) IntOrString {
+ return IntOrString{Type: String, StrVal: val}
+}
+
+// Parse the given string and try to convert it to an integer before
+// setting it as a string value.
+func Parse(val string) IntOrString {
+ i, err := strconv.Atoi(val)
+ if err != nil {
+ return FromString(val)
+ }
+ return FromInt(i)
+}
+
+// UnmarshalJSON implements the json.Unmarshaller interface.
+func (intstr *IntOrString) UnmarshalJSON(value []byte) error {
+ if value[0] == '"' {
+ intstr.Type = String
+ return json.Unmarshal(value, &intstr.StrVal)
+ }
+ intstr.Type = Int
+ return json.Unmarshal(value, &intstr.IntVal)
+}
+
+// String returns the string value, or the Itoa of the int value.
+func (intstr *IntOrString) String() string {
+ if intstr == nil {
+ return "<nil>"
+ }
+ if intstr.Type == String {
+ return intstr.StrVal
+ }
+ return strconv.Itoa(intstr.IntValue())
+}
+
+// IntValue returns the IntVal if type Int, or if
+// it is a String, will attempt a conversion to int,
+// returning 0 if a parsing error occurs.
+func (intstr *IntOrString) IntValue() int {
+ if intstr.Type == String {
+ i, _ := strconv.Atoi(intstr.StrVal)
+ return i
+ }
+ return int(intstr.IntVal)
+}
+
+// MarshalJSON implements the json.Marshaller interface.
+func (intstr IntOrString) MarshalJSON() ([]byte, error) {
+ switch intstr.Type {
+ case Int:
+ return json.Marshal(intstr.IntVal)
+ case String:
+ return json.Marshal(intstr.StrVal)
+ default:
+ return []byte{}, fmt.Errorf("impossible IntOrString.Type")
+ }
+}
diff --git a/pkg/kubeutils/resize.go b/pkg/kubeutils/resize.go
index 7b14b6db3..a744c66cc 100644
--- a/pkg/kubeutils/resize.go
+++ b/pkg/kubeutils/resize.go
@@ -18,7 +18,6 @@ package kubeutils
import (
"github.com/containers/podman/v4/libpod/define"
- "k8s.io/apimachinery/pkg/util/runtime"
)
// HandleResizing spawns a goroutine that processes the resize channel, calling resizeFunc for each
@@ -30,8 +29,6 @@ func HandleResizing(resize <-chan define.TerminalSize, resizeFunc func(size defi
}
go func() {
- defer runtime.HandleCrash()
-
for {
size, ok := <-resize
if !ok {
diff --git a/pkg/lookup/lookup.go b/pkg/lookup/lookup.go
index 0b22a1974..0601e829d 100644
--- a/pkg/lookup/lookup.go
+++ b/pkg/lookup/lookup.go
@@ -14,7 +14,7 @@ const (
etcgroup = "/etc/group"
)
-// Overrides allows you to override defaults in GetUserGroupInfo
+// Overrides allows you to override defaults in GetUserGroupInfo.
type Overrides struct {
DefaultUser *user.ExecUser
ContainerEtcPasswdPath string
diff --git a/pkg/machine/config.go b/pkg/machine/config.go
index efb1eda15..aaf8da872 100644
--- a/pkg/machine/config.go
+++ b/pkg/machine/config.go
@@ -1,3 +1,4 @@
+//go:build amd64 || arm64
// +build amd64 arm64
package machine
@@ -28,14 +29,16 @@ type InitOptions struct {
Username string
ReExec bool
Rootful bool
+ // The numberical userid of the user that called machine
+ UID string
}
type QemuMachineStatus = string
const (
- // Running indicates the qemu vm is running
+ // Running indicates the qemu vm is running.
Running QemuMachineStatus = "running"
- // Stopped indicates the vm has stopped
+ // Stopped indicates the vm has stopped.
Stopped QemuMachineStatus = "stopped"
DefaultMachineName string = "podman-machine-default"
)
@@ -144,7 +147,7 @@ func (rc RemoteConnectionType) MakeSSHURL(host, path, port, userName string) url
}
// GetDataDir returns the filepath where vm images should
-// live for podman-machine
+// live for podman-machine.
func GetDataDir(vmType string) (string, error) {
data, err := homedir.GetDataHome()
if err != nil {
diff --git a/pkg/machine/fcos.go b/pkg/machine/fcos.go
index 4d3e2edf4..6215ae08f 100644
--- a/pkg/machine/fcos.go
+++ b/pkg/machine/fcos.go
@@ -1,3 +1,4 @@
+//go:build amd64 || arm64
// +build amd64 arm64
package machine
diff --git a/pkg/machine/fedora.go b/pkg/machine/fedora.go
index cd713dde7..bed45c6da 100644
--- a/pkg/machine/fedora.go
+++ b/pkg/machine/fedora.go
@@ -1,3 +1,4 @@
+//go:build amd64 || arm64
// +build amd64 arm64
package machine
@@ -58,7 +59,10 @@ func (f FedoraDownload) Get() *Download {
func (f FedoraDownload) HasUsableCache() (bool, error) {
info, err := os.Stat(f.LocalPath)
if err != nil {
- return false, nil
+ if errors.Is(err, os.ErrNotExist) {
+ return false, nil
+ }
+ return false, err
}
return info.Size() == f.Size, nil
}
diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go
index 47b1836f0..b2dabb689 100644
--- a/pkg/machine/ignition.go
+++ b/pkg/machine/ignition.go
@@ -51,6 +51,7 @@ type DynamicIgnition struct {
Name string
Key string
TimeZone string
+ UID int
VMName string
WritePath string
}
@@ -63,12 +64,13 @@ func NewIgnitionFile(ign DynamicIgnition) error {
ignVersion := Ignition{
Version: "3.2.0",
}
-
ignPassword := Passwd{
Users: []PasswdUser{
{
Name: ign.Name,
SSHAuthorizedKeys: []SSHAuthorizedKey{SSHAuthorizedKey(ign.Key)},
+ // Set the UID of the core user inside the machine
+ UID: intToPtr(ign.UID),
},
{
Name: "root",
@@ -289,9 +291,7 @@ func getDirs(usrName string) []Directory {
}
func getFiles(usrName string) []File {
- var (
- files []File
- )
+ files := make([]File, 0)
lingerExample := `[Unit]
Description=A systemd user unit demo
@@ -310,6 +310,7 @@ machine_enabled=true
delegateConf := `[Service]
Delegate=memory pids cpu io
`
+ subUID := `%s:100000:1000000`
// Add a fake systemd service to get the user socket rolling
files = append(files, File{
@@ -344,6 +345,25 @@ Delegate=memory pids cpu io
},
})
+ // Setup /etc/subuid and /etc/subgid
+ for _, sub := range []string{"/etc/subuid", "/etc/subgid"} {
+ files = append(files, File{
+ Node: Node{
+ Group: getNodeGrp("root"),
+ Path: sub,
+ User: getNodeUsr("root"),
+ Overwrite: boolToPtr(true),
+ },
+ FileEmbedded1: FileEmbedded1{
+ Append: nil,
+ Contents: Resource{
+ Source: encodeDataURLPtr(fmt.Sprintf(subUID, usrName)),
+ },
+ Mode: intToPtr(0744),
+ },
+ })
+ }
+
// Set delegate.conf so cpu,io subsystem is delegated to non-root users as well for cgroupv2
// by default
files = append(files, File{
diff --git a/pkg/machine/ignition_darwin.go b/pkg/machine/ignition_darwin.go
index 9ede4b026..b9fbf218d 100644
--- a/pkg/machine/ignition_darwin.go
+++ b/pkg/machine/ignition_darwin.go
@@ -1,4 +1,5 @@
-//+build darwin
+//go:build darwin
+// +build darwin
package machine
diff --git a/pkg/machine/ignition_schema.go b/pkg/machine/ignition_schema.go
index 8cfb0d04e..d6b86229c 100644
--- a/pkg/machine/ignition_schema.go
+++ b/pkg/machine/ignition_schema.go
@@ -1,3 +1,4 @@
+//go:build amd64 || arm64
// +build amd64 arm64
package machine
diff --git a/pkg/machine/ignition_windows.go b/pkg/machine/ignition_windows.go
index c0de48bd3..0fcc06273 100644
--- a/pkg/machine/ignition_windows.go
+++ b/pkg/machine/ignition_windows.go
@@ -1,4 +1,5 @@
-//+build windows
+//go:build windows
+// +build windows
package machine
diff --git a/pkg/machine/keys.go b/pkg/machine/keys.go
index 711b091f0..15c1f73d8 100644
--- a/pkg/machine/keys.go
+++ b/pkg/machine/keys.go
@@ -1,3 +1,4 @@
+//go:build amd64 || arm64
// +build amd64 arm64
package machine
diff --git a/pkg/machine/machine_unsupported.go b/pkg/machine/machine_unsupported.go
index da1437984..a12140e16 100644
--- a/pkg/machine/machine_unsupported.go
+++ b/pkg/machine/machine_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !amd64 && !arm64
// +build !amd64,!arm64
package machine
diff --git a/pkg/machine/pull.go b/pkg/machine/pull.go
index 280b47f96..26abedfcd 100644
--- a/pkg/machine/pull.go
+++ b/pkg/machine/pull.go
@@ -1,3 +1,4 @@
+//go:build amd64 || arm64
// +build amd64 arm64
package machine
@@ -19,8 +20,8 @@ import (
"github.com/containers/storage/pkg/archive"
"github.com/sirupsen/logrus"
"github.com/ulikunitz/xz"
- "github.com/vbauerster/mpb/v6"
- "github.com/vbauerster/mpb/v6/decor"
+ "github.com/vbauerster/mpb/v7"
+ "github.com/vbauerster/mpb/v7/decor"
)
// GenericDownload is used when a user provides a URL
diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go
index c619b7dd4..211d96ccb 100644
--- a/pkg/machine/qemu/config.go
+++ b/pkg/machine/qemu/config.go
@@ -1,8 +1,11 @@
+//go:build (amd64 && !windows) || (arm64 && !windows)
// +build amd64,!windows arm64,!windows
package qemu
-import "time"
+import (
+ "time"
+)
type Provider struct{}
@@ -35,6 +38,8 @@ type MachineVM struct {
RemoteUsername string
// Whether this machine should run in a rootful or rootless manner
Rootful bool
+ // UID is the numerical id of the user that called machine
+ UID int
}
type Mount struct {
@@ -56,6 +61,6 @@ type Monitor struct {
var (
// defaultQMPTimeout is the timeout duration for the
- // qmp monitor interactions
+ // qmp monitor interactions.
defaultQMPTimeout time.Duration = 2 * time.Second
)
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index 9beec2173..3b14572a6 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -34,7 +34,7 @@ import (
var (
qemuProvider = &Provider{}
- // vmtype refers to qemu (vs libvirt, krun, etc)
+ // vmtype refers to qemu (vs libvirt, krun, etc).
vmtype = "qemu"
)
@@ -88,11 +88,16 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) {
vm.Memory = opts.Memory
vm.DiskSize = opts.DiskSize
- // Look up the executable
- execPath, err := exec.LookPath(QemuCommand)
+ // Find the qemu executable
+ cfg, err := config.Default()
+ if err != nil {
+ return nil, err
+ }
+ execPath, err := cfg.FindHelperBinary(QemuCommand, true)
if err != nil {
return nil, err
}
+
cmd := append([]string{execPath})
// Add memory
cmd = append(cmd, []string{"-m", strconv.Itoa(int(vm.Memory))}...)
@@ -129,7 +134,7 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) {
// LoadByName reads a json file that describes a known qemu vm
// and returns a vm instance
func (p *Provider) LoadVMByName(name string) (machine.VM, error) {
- vm := new(MachineVM)
+ vm := &MachineVM{UID: -1} // posix reserves -1, so use it to signify undefined
vmConfigDir, err := machine.GetConfDir(vmtype)
if err != nil {
return nil, err
@@ -245,12 +250,13 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
}
}
v.Mounts = mounts
+ v.UID = os.Getuid()
// Add location of bootable image
v.CmdLine = append(v.CmdLine, "-drive", "if=virtio,file="+v.ImagePath)
// This kind of stinks but no other way around this r/n
if len(opts.IgnitionPath) < 1 {
- uri := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/user/1000/podman/podman.sock", strconv.Itoa(v.Port), v.RemoteUsername)
+ uri := machine.SSHRemoteConnection.MakeSSHURL("localhost", fmt.Sprintf("/run/user/%d/podman/podman.sock", v.UID), strconv.Itoa(v.Port), v.RemoteUsername)
uriRoot := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/podman/podman.sock", strconv.Itoa(v.Port), "root")
identity := filepath.Join(sshDir, v.Name)
@@ -272,7 +278,9 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
fmt.Println("An ignition path was provided. No SSH connection was added to Podman")
}
// Write the JSON file
- v.writeConfig()
+ if err := v.writeConfig(); err != nil {
+ return false, fmt.Errorf("writing JSON file: %w", err)
+ }
// User has provided ignition file so keygen
// will be skipped.
@@ -296,7 +304,16 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
// only if the virtualdisk size is less than
// the given disk size
if opts.DiskSize<<(10*3) > originalDiskSize {
- resize := exec.Command("qemu-img", []string{"resize", v.ImagePath, strconv.Itoa(int(opts.DiskSize)) + "G"}...)
+ // Find the qemu executable
+ cfg, err := config.Default()
+ if err != nil {
+ return false, err
+ }
+ resizePath, err := cfg.FindHelperBinary("qemu-img", true)
+ if err != nil {
+ return false, err
+ }
+ resize := exec.Command(resizePath, []string{"resize", v.ImagePath, strconv.Itoa(int(opts.DiskSize)) + "G"}...)
resize.Stdout = os.Stdout
resize.Stderr = os.Stderr
if err := resize.Run(); err != nil {
@@ -319,6 +336,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
VMName: v.Name,
TimeZone: opts.TimeZone,
WritePath: v.IgnitionFilePath,
+ UID: v.UID,
}
err = machine.NewIgnitionFile(ign)
return err == nil, err
@@ -354,9 +372,13 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
conn net.Conn
err error
qemuSocketConn net.Conn
- wait time.Duration = time.Millisecond * 500
+ wait = time.Millisecond * 500
)
+ if v.isIncompatible() {
+ logrus.Errorf("machine %q is incompatible with this release of podman and needs to be recreated, starting for recovery only", v.Name)
+ }
+
forwardSock, forwardState, err := v.startHostNetworking()
if err != nil {
return errors.Errorf("unable to start host networking: %q", err)
@@ -459,7 +481,17 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
for _, mount := range v.Mounts {
fmt.Printf("Mounting volume... %s:%s\n", mount.Source, mount.Target)
// create mountpoint directory if it doesn't exist
- err = v.SSH(name, machine.SSHOptions{Args: []string{"-q", "--", "sudo", "mkdir", "-p", mount.Target}})
+ // because / is immutable, we have to monkey around with permissions
+ // if we dont mount in /home or /mnt
+ args := []string{"-q", "--"}
+ if !strings.HasPrefix(mount.Target, "/home") || !strings.HasPrefix(mount.Target, "/mnt") {
+ args = append(args, "sudo", "chattr", "-i", "/", ";")
+ }
+ args = append(args, "sudo", "mkdir", "-p", mount.Target)
+ if !strings.HasPrefix(mount.Target, "/home") || !strings.HasPrefix(mount.Target, "/mnt") {
+ args = append(args, ";", "sudo", "chattr", "+i", "/", ";")
+ }
+ err = v.SSH(name, machine.SSHOptions{Args: args})
if err != nil {
return err
}
@@ -480,7 +512,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
}
}
- waitAPIAndPrintInfo(forwardState, forwardSock, v.Rootful, v.Name)
+ v.waitAPIAndPrintInfo(forwardState, forwardSock)
return nil
}
@@ -596,7 +628,8 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error {
}
if err := qmpMonitor.Disconnect(); err != nil {
- return nil
+ // FIXME: this error should probably be returned
+ return nil // nolint: nilerr
}
disconnected = true
@@ -653,7 +686,7 @@ func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, fun
if err != nil {
return "", nil, err
}
- if running {
+ if running && !opts.Force {
return "", nil, errors.Errorf("running vm %q cannot be destroyed", v.Name)
}
@@ -667,6 +700,11 @@ func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, fun
if !opts.SaveImage {
files = append(files, v.ImagePath)
}
+ socketPath, err := v.getForwardSocketPath()
+ if err != nil {
+ logrus.Error(err)
+ }
+ files = append(files, socketPath)
files = append(files, v.archRemovalFiles()...)
if err := machine.RemoveConnection(v.Name); err != nil {
@@ -720,7 +758,8 @@ func (v *MachineVM) isRunning() (bool, error) {
// Check if we can dial it
monitor, err := qmp.NewSocketMonitor(v.QMPMonitor.Network, v.QMPMonitor.Address, v.QMPMonitor.Timeout)
if err != nil {
- return false, nil
+ // FIXME: this error should probably be returned
+ return false, nil // nolint: nilerr
}
if err := monitor.Connect(); err != nil {
return false, err
@@ -743,7 +782,7 @@ func (v *MachineVM) isRunning() (bool, error) {
func (v *MachineVM) isListening() bool {
// Check if we can dial it
- conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", "localhost", v.Port), 10*time.Millisecond)
+ conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", v.Port), 10*time.Millisecond)
if err != nil {
return false
}
@@ -790,7 +829,16 @@ func (v *MachineVM) SSH(name string, opts machine.SSHOptions) error {
// executes qemu-image info to get the virtual disk size
// of the diskimage
func getDiskSize(path string) (uint64, error) {
- diskInfo := exec.Command("qemu-img", "info", "--output", "json", path)
+ // Find the qemu executable
+ cfg, err := config.Default()
+ if err != nil {
+ return 0, err
+ }
+ qemuPathDir, err := cfg.FindHelperBinary("qemu-img", true)
+ if err != nil {
+ return 0, err
+ }
+ diskInfo := exec.Command(qemuPathDir, "info", "--output", "json", path)
stdout, err := diskInfo.StdoutPipe()
if err != nil {
return 0, err
@@ -935,7 +983,11 @@ func (v *MachineVM) startHostNetworking() (string, apiForwardingState, error) {
// Add the ssh port
cmd = append(cmd, []string{"-ssh-port", fmt.Sprintf("%d", v.Port)}...)
- cmd, forwardSock, state := v.setupAPIForwarding(cmd)
+ var forwardSock string
+ var state apiForwardingState
+ if !v.isIncompatible() {
+ cmd, forwardSock, state = v.setupAPIForwarding(cmd)
+ }
if logrus.GetLevel() == logrus.DebugLevel {
cmd = append(cmd, "--debug")
@@ -952,7 +1004,7 @@ func (v *MachineVM) setupAPIForwarding(cmd []string) ([]string, string, apiForwa
return cmd, "", noForwarding
}
- destSock := "/run/user/1000/podman/podman.sock"
+ destSock := fmt.Sprintf("/run/user/%d/podman/podman.sock", v.UID)
forwardUser := "core"
if v.Rootful {
@@ -1003,6 +1055,10 @@ func (v *MachineVM) setupAPIForwarding(cmd []string) ([]string, string, apiForwa
return cmd, dockerSock, dockerGlobal
}
+func (v *MachineVM) isIncompatible() bool {
+ return v.UID == -1
+}
+
func (v *MachineVM) getForwardSocketPath() (string, error) {
path, err := machine.GetDataDir(v.Name)
if err != nil {
@@ -1045,10 +1101,13 @@ func waitAndPingAPI(sock string) {
Transport: &http.Transport{
DialContext: func(context.Context, string, string) (net.Conn, error) {
con, err := net.DialTimeout("unix", sock, apiUpTimeout)
- if err == nil {
- con.SetDeadline(time.Now().Add(apiUpTimeout))
+ if err != nil {
+ return nil, err
+ }
+ if err := con.SetDeadline(time.Now().Add(apiUpTimeout)); err != nil {
+ return nil, err
}
- return con, err
+ return con, nil
},
},
}
@@ -1062,46 +1121,66 @@ func waitAndPingAPI(sock string) {
}
}
-func waitAPIAndPrintInfo(forwardState apiForwardingState, forwardSock string, rootFul bool, name string) {
- if forwardState != noForwarding {
- waitAndPingAPI(forwardSock)
- if !rootFul {
- fmt.Printf("\nThis machine is currently configured in rootless mode. If your containers\n")
- fmt.Printf("require root permissions (e.g. ports < 1024), or if you run into compatibility\n")
- fmt.Printf("issues with non-podman clients, you can switch using the following command: \n")
-
- suffix := ""
- if name != machine.DefaultMachineName {
- suffix = " " + name
- }
- fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix)
- }
+func (v *MachineVM) waitAPIAndPrintInfo(forwardState apiForwardingState, forwardSock string) {
+ suffix := ""
+ if v.Name != machine.DefaultMachineName {
+ suffix = " " + v.Name
+ }
- fmt.Printf("API forwarding listening on: %s\n", forwardSock)
- if forwardState == dockerGlobal {
- fmt.Printf("Docker API clients default to this address. You do not need to set DOCKER_HOST.\n\n")
- } else {
- stillString := "still "
- switch forwardState {
- case notInstalled:
- fmt.Printf("\nThe system helper service is not installed; the default Docker API socket\n")
- fmt.Printf("address can't be used by podman. ")
- if helper := findClaimHelper(); len(helper) > 0 {
- fmt.Printf("If you would like to install it run the\nfollowing command:\n")
- fmt.Printf("\n\tsudo %s install\n\n", helper)
- }
- case machineLocal:
- fmt.Printf("\nAnother process was listening on the default Docker API socket address.\n")
- case claimUnsupported:
- fallthrough
- default:
- stillString = ""
- }
+ if v.isIncompatible() {
+ fmt.Fprintf(os.Stderr, "\n!!! ACTION REQUIRED: INCOMPATIBLE MACHINE !!!\n")
+
+ fmt.Fprintf(os.Stderr, "\nThis machine was created by an older podman release that is incompatible\n")
+ fmt.Fprintf(os.Stderr, "with this release of podman. It has been started in a limited operational\n")
+ fmt.Fprintf(os.Stderr, "mode to allow you to copy any necessary files before recreating it. This\n")
+ fmt.Fprintf(os.Stderr, "can be accomplished with the following commands:\n\n")
+ fmt.Fprintf(os.Stderr, "\t# Login and copy desired files (Optional)\n")
+ fmt.Fprintf(os.Stderr, "\t# podman machine ssh%s tar cvPf - /path/to/files > backup.tar\n\n", suffix)
+ fmt.Fprintf(os.Stderr, "\t# Recreate machine (DESTRUCTIVE!) \n")
+ fmt.Fprintf(os.Stderr, "\tpodman machine stop%s\n", suffix)
+ fmt.Fprintf(os.Stderr, "\tpodman machine rm -f%s\n", suffix)
+ fmt.Fprintf(os.Stderr, "\tpodman machine init --now%s\n\n", suffix)
+ fmt.Fprintf(os.Stderr, "\t# Copy back files (Optional)\n")
+ fmt.Fprintf(os.Stderr, "\t# cat backup.tar | podman machine ssh%s tar xvPf - \n\n", suffix)
+ }
+
+ if forwardState == noForwarding {
+ return
+ }
- fmt.Printf("You can %sconnect Docker API clients by setting DOCKER_HOST using the\n", stillString)
- fmt.Printf("following command in your terminal session:\n")
- fmt.Printf("\n\texport DOCKER_HOST='unix://%s'\n\n", forwardSock)
+ waitAndPingAPI(forwardSock)
+ if !v.Rootful {
+ fmt.Printf("\nThis machine is currently configured in rootless mode. If your containers\n")
+ fmt.Printf("require root permissions (e.g. ports < 1024), or if you run into compatibility\n")
+ fmt.Printf("issues with non-podman clients, you can switch using the following command: \n")
+ fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix)
+ }
+
+ fmt.Printf("API forwarding listening on: %s\n", forwardSock)
+ if forwardState == dockerGlobal {
+ fmt.Printf("Docker API clients default to this address. You do not need to set DOCKER_HOST.\n\n")
+ } else {
+ stillString := "still "
+ switch forwardState {
+ case notInstalled:
+ fmt.Printf("\nThe system helper service is not installed; the default Docker API socket\n")
+ fmt.Printf("address can't be used by podman. ")
+ if helper := findClaimHelper(); len(helper) > 0 {
+ fmt.Printf("If you would like to install it run the\nfollowing commands:\n")
+ fmt.Printf("\n\tsudo %s install\n", helper)
+ fmt.Printf("\tpodman machine stop%s; podman machine start%s\n\n", suffix, suffix)
+ }
+ case machineLocal:
+ fmt.Printf("\nAnother process was listening on the default Docker API socket address.\n")
+ case claimUnsupported:
+ fallthrough
+ default:
+ stillString = ""
}
+
+ fmt.Printf("You can %sconnect Docker API clients by setting DOCKER_HOST using the\n", stillString)
+ fmt.Printf("following command in your terminal session:\n")
+ fmt.Printf("\n\texport DOCKER_HOST='unix://%s'\n\n", forwardSock)
}
}
diff --git a/pkg/machine/qemu/machine_unsupported.go b/pkg/machine/qemu/machine_unsupported.go
index e3ce05e3d..794e710f9 100644
--- a/pkg/machine/qemu/machine_unsupported.go
+++ b/pkg/machine/qemu/machine_unsupported.go
@@ -1,3 +1,4 @@
+//go:build (!amd64 && !arm64) || windows
// +build !amd64,!arm64 windows
package qemu
diff --git a/pkg/machine/qemu/options_darwin_arm64.go b/pkg/machine/qemu/options_darwin_arm64.go
index 727a275d2..5b6cdc86d 100644
--- a/pkg/machine/qemu/options_darwin_arm64.go
+++ b/pkg/machine/qemu/options_darwin_arm64.go
@@ -45,6 +45,7 @@ func getOvmfDir(imagePath, vmName string) string {
*/
func getEdk2CodeFd(name string) string {
dirs := []string{
+ "/opt/homebrew/opt/podman/libexec/share/qemu",
"/usr/local/share/qemu",
"/opt/homebrew/share/qemu",
}
diff --git a/pkg/machine/wsl/machine_unsupported.go b/pkg/machine/wsl/machine_unsupported.go
index 043c5d729..856f9dd0c 100644
--- a/pkg/machine/wsl/machine_unsupported.go
+++ b/pkg/machine/wsl/machine_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !windows
// +build !windows
package wsl
diff --git a/pkg/rootless/rootless.go b/pkg/rootless/rootless.go
index 93b4e2e9f..13f8078e2 100644
--- a/pkg/rootless/rootless.go
+++ b/pkg/rootless/rootless.go
@@ -1,6 +1,8 @@
package rootless
import (
+ "errors"
+ "fmt"
"os"
"sort"
"sync"
@@ -8,7 +10,6 @@ import (
"github.com/containers/storage/pkg/lockfile"
"github.com/opencontainers/runc/libcontainer/user"
spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
)
// TryJoinPauseProcess attempts to join the namespaces of the pause PID via
@@ -16,12 +17,15 @@ import (
// file.
func TryJoinPauseProcess(pausePidPath string) (bool, int, error) {
if _, err := os.Stat(pausePidPath); err != nil {
- return false, -1, nil
+ if errors.Is(err, os.ErrNotExist) {
+ return false, -1, nil
+ }
+ return false, -1, err
}
became, ret, err := TryJoinFromFilePaths("", false, []string{pausePidPath})
if err == nil {
- return became, ret, err
+ return became, ret, nil
}
// It could not join the pause process, let's lock the file before trying to delete it.
@@ -31,7 +35,7 @@ func TryJoinPauseProcess(pausePidPath string) (bool, int, error) {
if os.IsNotExist(err) {
return false, -1, nil
}
- return false, -1, errors.Wrapf(err, "error acquiring lock on %s", pausePidPath)
+ return false, -1, fmt.Errorf("error acquiring lock on %s: %w", pausePidPath, err)
}
pidFileLock.Lock()
@@ -46,7 +50,7 @@ func TryJoinPauseProcess(pausePidPath string) (bool, int, error) {
if err != nil {
// It is still failing. We can safely remove it.
os.Remove(pausePidPath)
- return false, -1, nil
+ return false, -1, nil // nolint: nilerr
}
return became, ret, err
}
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index a0b6edcfb..786e28093 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -1,3 +1,4 @@
+//go:build linux && cgo
// +build linux,cgo
package rootless
diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go
index 7dfb4a4b2..fe164e235 100644
--- a/pkg/rootless/rootless_unsupported.go
+++ b/pkg/rootless/rootless_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !linux || !cgo
// +build !linux !cgo
package rootless
diff --git a/pkg/rootlessport/rootlessport_linux.go b/pkg/rootlessport/rootlessport_linux.go
index b89a92d1e..6918a7e8c 100644
--- a/pkg/rootlessport/rootlessport_linux.go
+++ b/pkg/rootlessport/rootlessport_linux.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
// Package rootlessport provides reexec for RootlessKit-based port forwarder.
diff --git a/pkg/servicereaper/service.go b/pkg/servicereaper/service.go
index e105148f0..61445bc19 100644
--- a/pkg/servicereaper/service.go
+++ b/pkg/servicereaper/service.go
@@ -1,4 +1,5 @@
-//+build linux
+//go:build linux
+// +build linux
package servicereaper
diff --git a/pkg/signal/signal_common.go b/pkg/signal/signal_common.go
index 8ff4b4dbf..5ea67843a 100644
--- a/pkg/signal/signal_common.go
+++ b/pkg/signal/signal_common.go
@@ -25,7 +25,7 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) {
}
// ParseSignalNameOrNumber translates a string to a valid syscall signal. Input
-// can be a name or number representation i.e. "KILL" "9"
+// can be a name or number representation i.e. "KILL" "9".
func ParseSignalNameOrNumber(rawSignal string) (syscall.Signal, error) {
basename := strings.TrimPrefix(rawSignal, "-")
s, err := ParseSignal(basename)
diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go
index 305b9d21f..21e09c9fe 100644
--- a/pkg/signal/signal_linux.go
+++ b/pkg/signal/signal_linux.go
@@ -1,5 +1,5 @@
-// +build linux
-// +build !mips,!mipsle,!mips64,!mips64le
+//go:build linux && !mips && !mipsle && !mips64 && !mips64le
+// +build linux,!mips,!mipsle,!mips64,!mips64le
// Signal handling for Linux only.
package signal
diff --git a/pkg/signal/signal_linux_mipsx.go b/pkg/signal/signal_linux_mipsx.go
index 45c9d5af1..52b07aaf4 100644
--- a/pkg/signal/signal_linux_mipsx.go
+++ b/pkg/signal/signal_linux_mipsx.go
@@ -1,3 +1,4 @@
+//go:build linux && (mips || mipsle || mips64 || mips64le)
// +build linux
// +build mips mipsle mips64 mips64le
diff --git a/pkg/signal/signal_unix.go b/pkg/signal/signal_unix.go
new file mode 100644
index 000000000..c0aa62d21
--- /dev/null
+++ b/pkg/signal/signal_unix.go
@@ -0,0 +1,100 @@
+//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd || solaris || zos
+// +build aix darwin dragonfly freebsd netbsd openbsd solaris zos
+
+// Signal handling for Linux only.
+package signal
+
+import (
+ "os"
+ "syscall"
+)
+
+const (
+ sigrtmin = 34
+ sigrtmax = 64
+
+ SIGWINCH = syscall.SIGWINCH
+)
+
+// signalMap is a map of Linux signals.
+// These constants are sourced from the Linux version of golang.org/x/sys/unix
+// (I don't see much risk of this changing).
+// This should work as long as Podman only runs containers on Linux, which seems
+// a safe assumption for now.
+var signalMap = map[string]syscall.Signal{
+ "ABRT": syscall.Signal(0x6),
+ "ALRM": syscall.Signal(0xe),
+ "BUS": syscall.Signal(0x7),
+ "CHLD": syscall.Signal(0x11),
+ "CLD": syscall.Signal(0x11),
+ "CONT": syscall.Signal(0x12),
+ "FPE": syscall.Signal(0x8),
+ "HUP": syscall.Signal(0x1),
+ "ILL": syscall.Signal(0x4),
+ "INT": syscall.Signal(0x2),
+ "IO": syscall.Signal(0x1d),
+ "IOT": syscall.Signal(0x6),
+ "KILL": syscall.Signal(0x9),
+ "PIPE": syscall.Signal(0xd),
+ "POLL": syscall.Signal(0x1d),
+ "PROF": syscall.Signal(0x1b),
+ "PWR": syscall.Signal(0x1e),
+ "QUIT": syscall.Signal(0x3),
+ "SEGV": syscall.Signal(0xb),
+ "STKFLT": syscall.Signal(0x10),
+ "STOP": syscall.Signal(0x13),
+ "SYS": syscall.Signal(0x1f),
+ "TERM": syscall.Signal(0xf),
+ "TRAP": syscall.Signal(0x5),
+ "TSTP": syscall.Signal(0x14),
+ "TTIN": syscall.Signal(0x15),
+ "TTOU": syscall.Signal(0x16),
+ "URG": syscall.Signal(0x17),
+ "USR1": syscall.Signal(0xa),
+ "USR2": syscall.Signal(0xc),
+ "VTALRM": syscall.Signal(0x1a),
+ "WINCH": syscall.Signal(0x1c),
+ "XCPU": syscall.Signal(0x18),
+ "XFSZ": syscall.Signal(0x19),
+ "RTMIN": sigrtmin,
+ "RTMIN+1": sigrtmin + 1,
+ "RTMIN+2": sigrtmin + 2,
+ "RTMIN+3": sigrtmin + 3,
+ "RTMIN+4": sigrtmin + 4,
+ "RTMIN+5": sigrtmin + 5,
+ "RTMIN+6": sigrtmin + 6,
+ "RTMIN+7": sigrtmin + 7,
+ "RTMIN+8": sigrtmin + 8,
+ "RTMIN+9": sigrtmin + 9,
+ "RTMIN+10": sigrtmin + 10,
+ "RTMIN+11": sigrtmin + 11,
+ "RTMIN+12": sigrtmin + 12,
+ "RTMIN+13": sigrtmin + 13,
+ "RTMIN+14": sigrtmin + 14,
+ "RTMIN+15": sigrtmin + 15,
+ "RTMAX-14": sigrtmax - 14,
+ "RTMAX-13": sigrtmax - 13,
+ "RTMAX-12": sigrtmax - 12,
+ "RTMAX-11": sigrtmax - 11,
+ "RTMAX-10": sigrtmax - 10,
+ "RTMAX-9": sigrtmax - 9,
+ "RTMAX-8": sigrtmax - 8,
+ "RTMAX-7": sigrtmax - 7,
+ "RTMAX-6": sigrtmax - 6,
+ "RTMAX-5": sigrtmax - 5,
+ "RTMAX-4": sigrtmax - 4,
+ "RTMAX-3": sigrtmax - 3,
+ "RTMAX-2": sigrtmax - 2,
+ "RTMAX-1": sigrtmax - 1,
+ "RTMAX": sigrtmax,
+}
+
+// CatchAll catches all signals and relays them to the specified channel.
+func CatchAll(sigc chan os.Signal) {
+ panic("Unsupported on non-linux platforms")
+}
+
+// StopCatch stops catching the signals and closes the specified channel.
+func StopCatch(sigc chan os.Signal) {
+ panic("Unsupported on non-linux platforms")
+}
diff --git a/pkg/signal/signal_unsupported.go b/pkg/signal/signal_unsupported.go
index 9d1733c02..d8bba7c90 100644
--- a/pkg/signal/signal_unsupported.go
+++ b/pkg/signal/signal_unsupported.go
@@ -1,4 +1,5 @@
-// +build !linux
+//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos
+// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos
// Signal handling for Linux only.
package signal
diff --git a/pkg/specgen/config_unsupported.go b/pkg/specgen/config_unsupported.go
index 70a60ac47..a6bf77277 100644
--- a/pkg/specgen/config_unsupported.go
+++ b/pkg/specgen/config_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package specgen
diff --git a/pkg/specgen/generate/config_linux.go b/pkg/specgen/generate/config_linux.go
index a5772bc6a..35d7f0252 100644
--- a/pkg/specgen/generate/config_linux.go
+++ b/pkg/specgen/generate/config_linux.go
@@ -262,8 +262,8 @@ func addDevice(g *generate.Generator, device string) error {
// ParseDevice parses device mapping string to a src, dest & permissions string
func ParseDevice(device string) (string, string, string, error) { //nolint
- src := ""
- dst := ""
+ var src string
+ var dst string
permissions := "rwm"
arr := strings.Split(device, ":")
switch len(arr) {
diff --git a/pkg/specgen/generate/config_linux_cgo.go b/pkg/specgen/generate/config_linux_cgo.go
index 239655c72..efab6679a 100644
--- a/pkg/specgen/generate/config_linux_cgo.go
+++ b/pkg/specgen/generate/config_linux_cgo.go
@@ -1,3 +1,4 @@
+//go:build linux && cgo
// +build linux,cgo
package generate
diff --git a/pkg/specgen/generate/config_linux_nocgo.go b/pkg/specgen/generate/config_linux_nocgo.go
index 9ead739a7..99b0c4eb2 100644
--- a/pkg/specgen/generate/config_linux_nocgo.go
+++ b/pkg/specgen/generate/config_linux_nocgo.go
@@ -1,3 +1,4 @@
+//go:build linux && !cgo
// +build linux,!cgo
package generate
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index c0b23953f..8ab0eae5a 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -526,6 +526,10 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
options = append(options, libpod.WithPidFile(s.PidFile))
}
+ if len(s.ChrootDirs) != 0 {
+ options = append(options, libpod.WithChrootDirs(s.ChrootDirs))
+ }
+
options = append(options, libpod.WithSelectedPasswordManagement(s.Passwd))
return options, nil
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index 5e6671231..df751a780 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -20,6 +20,8 @@ import (
"github.com/containers/podman/v4/libpod/define"
ann "github.com/containers/podman/v4/pkg/annotations"
"github.com/containers/podman/v4/pkg/domain/entities"
+ v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
+ "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/api/resource"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/pkg/specgen/generate"
"github.com/containers/podman/v4/pkg/util"
@@ -27,8 +29,6 @@ import (
"github.com/docker/go-units"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
- v1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/api/resource"
)
func ToPodOpt(ctx context.Context, podName string, p entities.PodCreateOptions, podYAML *v1.PodTemplateSpec) (entities.PodCreateOptions, error) {
@@ -277,7 +277,13 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
}
annotations := make(map[string]string)
+ if opts.Annotations != nil {
+ annotations = opts.Annotations
+ }
if opts.PodInfraID != "" {
+ if annotations == nil {
+
+ }
annotations[ann.SandboxID] = opts.PodInfraID
annotations[ann.ContainerType] = ann.ContainerTypeContainer
}
diff --git a/pkg/specgen/generate/kube/kube_test.go b/pkg/specgen/generate/kube/kube_test.go
index 62793ebb6..0898d427d 100644
--- a/pkg/specgen/generate/kube/kube_test.go
+++ b/pkg/specgen/generate/kube/kube_test.go
@@ -3,8 +3,8 @@ package kube
import (
"testing"
+ v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
"github.com/stretchr/testify/assert"
- v1 "k8s.io/api/core/v1"
//"github.com/stretchr/testify/require"
)
diff --git a/pkg/specgen/generate/kube/play_test.go b/pkg/specgen/generate/kube/play_test.go
index 6798fdb1b..448522c2a 100644
--- a/pkg/specgen/generate/kube/play_test.go
+++ b/pkg/specgen/generate/kube/play_test.go
@@ -11,11 +11,11 @@ import (
"testing"
"github.com/containers/common/pkg/secrets"
+ v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
+ "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/api/resource"
+ v12 "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/docker/docker/pkg/system"
"github.com/stretchr/testify/assert"
- v1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/api/resource"
- v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func createSecrets(t *testing.T, d string) *secrets.SecretsManager {
diff --git a/pkg/specgen/generate/kube/seccomp.go b/pkg/specgen/generate/kube/seccomp.go
index b977b6f50..1e681e977 100644
--- a/pkg/specgen/generate/kube/seccomp.go
+++ b/pkg/specgen/generate/kube/seccomp.go
@@ -5,8 +5,8 @@ import (
"strings"
"github.com/containers/podman/v4/libpod"
+ v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
"github.com/pkg/errors"
- v1 "k8s.io/api/core/v1"
)
// KubeSeccompPaths holds information about a pod YAML's seccomp configuration
diff --git a/pkg/specgen/generate/kube/volume.go b/pkg/specgen/generate/kube/volume.go
index 01f731b60..d57cb5685 100644
--- a/pkg/specgen/generate/kube/volume.go
+++ b/pkg/specgen/generate/kube/volume.go
@@ -5,9 +5,9 @@ import (
"github.com/containers/common/pkg/parse"
"github.com/containers/podman/v4/libpod"
+ v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
- v1 "k8s.io/api/core/v1"
)
const (
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index 8b3550e36..1cc3a463f 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -332,6 +332,11 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
}
// Devices
+ // set the default rule at the beginning of device configuration
+ if !inUserNS && !s.Privileged {
+ g.AddLinuxResourcesDevice(false, "", nil, nil, "rwm")
+ }
+
var userDevices []spec.LinuxDevice
if s.Privileged {
// If privileged, we need to add all the host devices to the
@@ -363,7 +368,6 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
// set the devices cgroup when not running in a user namespace
if !inUserNS && !s.Privileged {
- g.AddLinuxResourcesDevice(false, "", nil, nil, "rwm")
for _, dev := range s.DeviceCgroupRule {
g.AddLinuxResourcesDevice(true, dev.Type, dev.Major, dev.Minor, dev.Access)
}
diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go
index 8450fe7ce..ba823f3a8 100644
--- a/pkg/specgen/generate/pod_create.go
+++ b/pkg/specgen/generate/pod_create.go
@@ -56,6 +56,7 @@ ENTRYPOINT ["/catatonit", "-P"]`, catatonitPath)
CommonBuildOpts: &buildahDefine.CommonBuildOptions{},
Output: imageName,
Quiet: true,
+ IgnoreFile: "/dev/null", // makes sure to not read a local .ignorefile (see #13529)
IIDFile: "/dev/null", // prevents Buildah from writing the ID on stdout
}
if _, _, err := rt.Build(context.Background(), buildOptions, tmpF.Name()); err != nil {
diff --git a/pkg/specgen/generate/ports_bench_test.go b/pkg/specgen/generate/ports_bench_test.go
index f208a34c5..f65cd2f15 100644
--- a/pkg/specgen/generate/ports_bench_test.go
+++ b/pkg/specgen/generate/ports_bench_test.go
@@ -9,7 +9,7 @@ import (
func benchmarkParsePortMapping(b *testing.B, ports []types.PortMapping) {
for n := 0; n < b.N; n++ {
- ParsePortMapping(ports, nil)
+ _, _ = ParsePortMapping(ports, nil)
}
}
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
index 7f6f79b87..27d77af9f 100644
--- a/pkg/specgen/specgen.go
+++ b/pkg/specgen/specgen.go
@@ -301,6 +301,10 @@ type ContainerStorageConfig struct {
// Volatile specifies whether the container storage can be optimized
// at the cost of not syncing all the dirty files in memory.
Volatile bool `json:"volatile,omitempty"`
+ // ChrootDirs is an additional set of directories that need to be
+ // treated as root directories. Standard bind mounts will be mounted
+ // into paths relative to these directories.
+ ChrootDirs []string `json:"chroot_directories,omitempty"`
}
// ContainerSecurityConfig is a container's security features, including
diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go
index b037e14cc..688cc2337 100644
--- a/pkg/specgenutil/specgen.go
+++ b/pkg/specgenutil/specgen.go
@@ -819,6 +819,9 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
if !s.UnsetEnvAll {
s.UnsetEnvAll = c.UnsetEnvAll
}
+ if len(s.ChrootDirs) == 0 || len(c.ChrootDirs) != 0 {
+ s.ChrootDirs = c.ChrootDirs
+ }
// Initcontainers
if len(s.InitContainerType) == 0 || len(c.InitContainerType) != 0 {
@@ -844,7 +847,8 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start
if len(cmdArr) == 0 {
return nil, errors.New("Must define a healthcheck command for all healthchecks")
}
- concat := ""
+
+ var concat string
if cmdArr[0] == "CMD" || cmdArr[0] == "none" { // this is for compat, we are already split properly for most compat cases
cmdArr = strings.Fields(inCmd)
} else if cmdArr[0] != "CMD-SHELL" { // this is for podman side of things, won't contain the keywords
diff --git a/pkg/systemd/dbus.go b/pkg/systemd/dbus.go
index 1b1bc8be9..44feb8308 100644
--- a/pkg/systemd/dbus.go
+++ b/pkg/systemd/dbus.go
@@ -24,7 +24,6 @@ func IsSystemdSessionValid(uid int) bool {
if rootless.IsRootless() {
conn, err = GetLogindConnection(rootless.GetRootlessUID())
- object = conn.Object(dbusDest, godbus.ObjectPath(dbusPath))
if err != nil {
//unable to fetch systemd object for logind
logrus.Debugf("systemd-logind: %s", err)
diff --git a/pkg/systemd/generate/common.go b/pkg/systemd/generate/common.go
index a6f8f7cd4..e53d37897 100644
--- a/pkg/systemd/generate/common.go
+++ b/pkg/systemd/generate/common.go
@@ -137,3 +137,17 @@ func removeArg(arg string, args []string) []string {
}
return newArgs
}
+
+// This function is used to get name of systemd service from prefix, separator, and
+// container/pod name. If prefix is empty, the service name does not include the
+// separator. This is to avoid a situation where service name starts with the separator
+// which is usually hyphen.
+func getServiceName(prefix string, separator string, name string) string {
+ serviceName := name
+
+ if len(prefix) > 0 {
+ serviceName = prefix + separator + name
+ }
+
+ return serviceName
+}
diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go
index ea829c810..e11aed771 100644
--- a/pkg/systemd/generate/containers.go
+++ b/pkg/systemd/generate/containers.go
@@ -236,7 +236,9 @@ func containerServiceName(ctr *libpod.Container, options entities.GenerateSystem
if options.Name {
nameOrID = ctr.Name()
}
- serviceName := fmt.Sprintf("%s%s%s", options.ContainerPrefix, options.Separator, nameOrID)
+
+ serviceName := getServiceName(options.ContainerPrefix, options.Separator, nameOrID)
+
return nameOrID, serviceName
}
@@ -360,7 +362,9 @@ func executeContainerTemplate(info *containerInfo, options entities.GenerateSyst
fs.StringArrayP("env", "e", nil, "")
fs.String("sdnotify", "", "")
fs.String("restart", "", "")
- fs.Parse(remainingCmd)
+ if err := fs.Parse(remainingCmd); err != nil {
+ return "", fmt.Errorf("parsing remaining command-line arguments: %w", err)
+ }
remainingCmd = filterCommonContainerFlags(remainingCmd, fs.NArg())
// If the container is in a pod, make sure that the
diff --git a/pkg/systemd/generate/containers_test.go b/pkg/systemd/generate/containers_test.go
index 2f653a4b9..b9bf7c317 100644
--- a/pkg/systemd/generate/containers_test.go
+++ b/pkg/systemd/generate/containers_test.go
@@ -91,6 +91,30 @@ Type=forking
WantedBy=default.target
`
+ goodNameEmptyContainerPrefix := `# foobar.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman foobar.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+TimeoutStopSec=70
+ExecStart=/usr/bin/podman start foobar
+ExecStop=/usr/bin/podman stop -t 10 foobar
+ExecStopPost=/usr/bin/podman stop -t 10 foobar
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
+
goodNameCustomWants := `# container-foobar.service
# autogenerated by Podman CI
@@ -1206,6 +1230,24 @@ WantedBy=default.target
false,
true,
},
+ {"good with name and empty container-prefix",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "foobar",
+ ContainerNameOrID: "foobar",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ EnvVariable: define.EnvVariable,
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ },
+ goodNameEmptyContainerPrefix,
+ false,
+ false,
+ false,
+ false,
+ },
}
for _, tt := range tests {
test := tt
diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go
index 003c23e77..15b598ae8 100644
--- a/pkg/systemd/generate/pods.go
+++ b/pkg/systemd/generate/pods.go
@@ -242,7 +242,8 @@ func generatePodInfo(pod *libpod.Pod, options entities.GenerateSystemdOptions) (
nameOrID = pod.Name()
ctrNameOrID = infraCtr.Name()
}
- serviceName := fmt.Sprintf("%s%s%s", options.PodPrefix, options.Separator, nameOrID)
+
+ serviceName := getServiceName(options.PodPrefix, options.Separator, nameOrID)
info := podInfo{
ServiceName: serviceName,
@@ -334,7 +335,9 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions)
fs.SetInterspersed(false)
fs.String("name", "", "")
fs.Bool("replace", false, "")
- fs.Parse(podCreateArgs)
+ if err := fs.Parse(podCreateArgs); err != nil {
+ return "", fmt.Errorf("parsing remaining command-line arguments: %w", err)
+ }
hasNameParam := fs.Lookup("name").Changed
hasReplaceParam, err := fs.GetBool("replace")
diff --git a/pkg/systemd/generate/pods_test.go b/pkg/systemd/generate/pods_test.go
index b37e0825b..dcb18780c 100644
--- a/pkg/systemd/generate/pods_test.go
+++ b/pkg/systemd/generate/pods_test.go
@@ -67,6 +67,32 @@ WantedBy=default.target
podGood := serviceInfo + headerInfo + podContent
podGoodNoHeaderInfo := serviceInfo + podContent
+ podGoodWithEmptyPrefix := `# 123abc.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman 123abc.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+Requires=container-1.service container-2.service
+Before=container-1.service container-2.service
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+TimeoutStopSec=102
+ExecStart=/usr/bin/podman start jadda-jadda-infra
+ExecStop=/usr/bin/podman stop -t 42 jadda-jadda-infra
+ExecStopPost=/usr/bin/podman stop -t 42 jadda-jadda-infra
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
+
podGoodCustomWants := `# pod-123abc.service
# autogenerated by Podman CI
@@ -580,6 +606,24 @@ WantedBy=default.target
false,
false,
},
+ {"pod with empty pod-prefix",
+ podInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "123abc",
+ InfraNameOrID: "jadda-jadda-infra",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 42,
+ PodmanVersion: "CI",
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ RequiredServices: []string{"container-1", "container-2"},
+ CreateCommand: []string{"podman", "pod", "create", "--name", "foo", "bar=arg with space"},
+ },
+ podGoodWithEmptyPrefix,
+ false,
+ false,
+ false,
+ },
}
for _, tt := range tests {
diff --git a/pkg/terminal/console_unix.go b/pkg/terminal/console_unix.go
index 6eee6aa2f..53290be24 100644
--- a/pkg/terminal/console_unix.go
+++ b/pkg/terminal/console_unix.go
@@ -1,8 +1,9 @@
+//go:build !windows
// +build !windows
package terminal
-// SetConsole for non-windows environments is a no-op
+// SetConsole for non-windows environments is a no-op.
func SetConsole() error {
return nil
}
diff --git a/pkg/terminal/console_windows.go b/pkg/terminal/console_windows.go
index 9a636d681..1a7da3335 100644
--- a/pkg/terminal/console_windows.go
+++ b/pkg/terminal/console_windows.go
@@ -1,3 +1,4 @@
+//go:build windows
// +build windows
package terminal
diff --git a/pkg/util/camelcase/camelcase.go b/pkg/util/camelcase/camelcase.go
index d27ac00d6..eaf7c0178 100644
--- a/pkg/util/camelcase/camelcase.go
+++ b/pkg/util/camelcase/camelcase.go
@@ -51,10 +51,10 @@ func Split(src string) (entries []string) {
}
entries = []string{}
var runes [][]rune
- lastClass := 0
- class := 0
+ var lastClass int
// split into fields based on class of unicode character
for _, r := range src {
+ var class int
switch {
case unicode.IsLower(r):
class = 1
diff --git a/pkg/util/mountOpts_other.go b/pkg/util/mountOpts_other.go
index 6a34942e5..64b4dd1d9 100644
--- a/pkg/util/mountOpts_other.go
+++ b/pkg/util/mountOpts_other.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package util
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index bdd1e1383..1beb3b28e 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -463,6 +463,8 @@ func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []strin
var (
rootlessConfigHomeDirOnce sync.Once
rootlessConfigHomeDir string
+ rootlessRuntimeDirOnce sync.Once
+ rootlessRuntimeDir string
)
type tomlOptionsConfig struct {
@@ -725,7 +727,7 @@ func SocketPath() (string, error) {
func LookupUser(name string) (*user.User, error) {
// Assume UID look up first, if it fails lookup by username
if u, err := user.LookupId(name); err == nil {
- return u, err
+ return u, nil
}
return user.Lookup(name)
}
diff --git a/pkg/util/utils_darwin.go b/pkg/util/utils_darwin.go
index 33a46a5d4..66ae85e9c 100644
--- a/pkg/util/utils_darwin.go
+++ b/pkg/util/utils_darwin.go
@@ -1,4 +1,5 @@
-//+build darwin
+//go:build darwin
+// +build darwin
package util
diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go
index e9d6bfa31..50e4b1b7b 100644
--- a/pkg/util/utils_supported.go
+++ b/pkg/util/utils_supported.go
@@ -1,3 +1,4 @@
+//go:build !windows
// +build !windows
package util
@@ -6,21 +7,67 @@ package util
// should work to take darwin from this
import (
+ "fmt"
"os"
"path/filepath"
"syscall"
- cutil "github.com/containers/common/pkg/util"
"github.com/containers/podman/v4/pkg/rootless"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
// GetRuntimeDir returns the runtime directory
func GetRuntimeDir() (string, error) {
+ var rootlessRuntimeDirError error
+
if !rootless.IsRootless() {
return "", nil
}
- return cutil.GetRuntimeDir()
+
+ rootlessRuntimeDirOnce.Do(func() {
+ runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
+ uid := fmt.Sprintf("%d", rootless.GetRootlessUID())
+ if runtimeDir == "" {
+ tmpDir := filepath.Join("/run", "user", uid)
+ if err := os.MkdirAll(tmpDir, 0700); err != nil {
+ logrus.Debug(err)
+ }
+ st, err := os.Stat(tmpDir)
+ if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && (st.Mode().Perm()&0700 == 0700) {
+ runtimeDir = tmpDir
+ }
+ }
+ if runtimeDir == "" {
+ tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("podman-run-%s", uid))
+ if err := os.MkdirAll(tmpDir, 0700); err != nil {
+ logrus.Debug(err)
+ }
+ st, err := os.Stat(tmpDir)
+ if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && (st.Mode().Perm()&0700 == 0700) {
+ runtimeDir = tmpDir
+ }
+ }
+ if runtimeDir == "" {
+ home := os.Getenv("HOME")
+ if home == "" {
+ rootlessRuntimeDirError = fmt.Errorf("neither XDG_RUNTIME_DIR nor HOME was set non-empty")
+ return
+ }
+ resolvedHome, err := filepath.EvalSymlinks(home)
+ if err != nil {
+ rootlessRuntimeDirError = errors.Wrapf(err, "cannot resolve %s", home)
+ return
+ }
+ runtimeDir = filepath.Join(resolvedHome, "rundir")
+ }
+ rootlessRuntimeDir = runtimeDir
+ })
+
+ if rootlessRuntimeDirError != nil {
+ return "", rootlessRuntimeDirError
+ }
+ return rootlessRuntimeDir, nil
}
// GetRootlessConfigHomeDir returns the config home directory when running as non root
diff --git a/pkg/util/utils_unsupported.go b/pkg/util/utils_unsupported.go
index 62805d7c8..896346493 100644
--- a/pkg/util/utils_unsupported.go
+++ b/pkg/util/utils_unsupported.go
@@ -1,3 +1,4 @@
+//go:build darwin || windows
// +build darwin windows
package util
diff --git a/pkg/util/utils_windows.go b/pkg/util/utils_windows.go
index 46ca5e7f1..2732124f2 100644
--- a/pkg/util/utils_windows.go
+++ b/pkg/util/utils_windows.go
@@ -1,3 +1,4 @@
+//go:build windows
// +build windows
package util