Merge pull request #19102 from jakecorrenti/kube-generate-print-annotations

Add `--no-trunc` flag to maintain original annotation length
This commit is contained in:
OpenShift Merge Robot
2023-07-10 22:41:39 -04:00
committed by GitHub
20 changed files with 269 additions and 42 deletions

View File

@ -81,6 +81,9 @@ func generateFlags(cmd *cobra.Command, podmanConfig *entities.PodmanConfig) {
flags.Int32VarP(&generateOptions.Replicas, replicasFlagName, "r", 1, "Set the replicas number for Deployment kind") flags.Int32VarP(&generateOptions.Replicas, replicasFlagName, "r", 1, "Set the replicas number for Deployment kind")
_ = cmd.RegisterFlagCompletionFunc(replicasFlagName, completion.AutocompleteNone) _ = cmd.RegisterFlagCompletionFunc(replicasFlagName, completion.AutocompleteNone)
noTruncAnnotationsFlagName := "no-trunc"
flags.BoolVar(&generateOptions.UseLongAnnotations, noTruncAnnotationsFlagName, false, "Don't truncate annotations to Kubernetes length (63 chars)")
flags.SetNormalizeFunc(utils.AliasFlags) flags.SetNormalizeFunc(utils.AliasFlags)
} }

View File

@ -165,6 +165,9 @@ func playFlags(cmd *cobra.Command) {
flags.StringSliceVar(&playOptions.ConfigMaps, configmapFlagName, []string{}, "`Pathname` of a YAML file containing a kubernetes configmap") flags.StringSliceVar(&playOptions.ConfigMaps, configmapFlagName, []string{}, "`Pathname` of a YAML file containing a kubernetes configmap")
_ = cmd.RegisterFlagCompletionFunc(configmapFlagName, completion.AutocompleteDefault) _ = cmd.RegisterFlagCompletionFunc(configmapFlagName, completion.AutocompleteDefault)
noTruncFlagName := "no-trunc"
flags.BoolVar(&playOptions.UseLongAnnotations, noTruncFlagName, false, "Use annotations that are not truncated to the Kubernetes maximum length of 63 characters")
if !registry.IsRemote() { if !registry.IsRemote() {
certDirFlagName := "cert-dir" certDirFlagName := "cert-dir"
flags.StringVar(&playOptions.CertDir, certDirFlagName, "", "`Pathname` of a directory containing TLS certificates and keys") flags.StringVar(&playOptions.CertDir, certDirFlagName, "", "`Pathname` of a directory containing TLS certificates and keys")
@ -240,7 +243,7 @@ func play(cmd *cobra.Command, args []string) error {
playOptions.Annotations = make(map[string]string) playOptions.Annotations = make(map[string]string)
} }
annotation := splitN[1] annotation := splitN[1]
if len(annotation) > define.MaxKubeAnnotation { if len(annotation) > define.MaxKubeAnnotation && !playOptions.UseLongAnnotations {
return fmt.Errorf("annotation exceeds maximum size, %d, of kubernetes annotation: %s", define.MaxKubeAnnotation, annotation) return fmt.Errorf("annotation exceeds maximum size, %d, of kubernetes annotation: %s", define.MaxKubeAnnotation, annotation)
} }
playOptions.Annotations[splitN[0]] = annotation playOptions.Annotations[splitN[0]] = annotation

View File

@ -34,6 +34,11 @@ Note that the generated Kubernetes YAML file can be used to re-run the deploymen
Output to the given file instead of STDOUT. If the file already exists, `kube generate` refuses to replace it and returns an error. Output to the given file instead of STDOUT. If the file already exists, `kube generate` refuses to replace it and returns an error.
#### **--no-trunc**
Don't truncate annotations to the Kubernetes maximum length of 63 characters.
Note: enabling this flag means the generated YAML file is not Kubernetes compatible and can only be used with `podman kube play`
#### **--replicas**, **-r**=*replica count* #### **--replicas**, **-r**=*replica count*
The value to set `replicas` to when generating a **Deployment** kind. The value to set `replicas` to when generating a **Deployment** kind.

View File

@ -214,6 +214,10 @@ When no network option is specified and *host* network mode is not configured in
This option conflicts with host added in the Kubernetes YAML. This option conflicts with host added in the Kubernetes YAML.
#### **--no-trunc**
Use annotations that are not truncated to the Kubernetes maximum length of 63 characters
#### **--publish**=*[[ip:][hostPort]:]containerPort[/protocol]* #### **--publish**=*[[ip:][hostPort]:]containerPort[/protocol]*
Define or override a port definition in the YAML file. Define or override a port definition in the YAML file.

View File

@ -34,14 +34,14 @@ import (
// GenerateForKube takes a slice of libpod containers and generates // GenerateForKube takes a slice of libpod containers and generates
// one v1.Pod description that includes just a single container. // one v1.Pod description that includes just a single container.
func GenerateForKube(ctx context.Context, ctrs []*Container, getService bool) (*v1.Pod, error) { func GenerateForKube(ctx context.Context, ctrs []*Container, getService, useLongAnnotations bool) (*v1.Pod, error) {
// Generate the v1.Pod yaml description // Generate the v1.Pod yaml description
return simplePodWithV1Containers(ctx, ctrs, getService) return simplePodWithV1Containers(ctx, ctrs, getService, useLongAnnotations)
} }
// GenerateForKube takes a slice of libpod containers and generates // GenerateForKube takes a slice of libpod containers and generates
// one v1.Pod description // one v1.Pod description
func (p *Pod) GenerateForKube(ctx context.Context, getService bool) (*v1.Pod, []v1.ServicePort, error) { func (p *Pod) GenerateForKube(ctx context.Context, getService, useLongAnnotations bool) (*v1.Pod, []v1.ServicePort, error) {
// Generate the v1.Pod yaml description // Generate the v1.Pod yaml description
var ( var (
ports []v1.ContainerPort ports []v1.ContainerPort
@ -91,7 +91,7 @@ func (p *Pod) GenerateForKube(ctx context.Context, getService bool) (*v1.Pod, []
hostNetwork = infraContainer.NetworkMode() == string(namespaces.NetworkMode(specgen.Host)) hostNetwork = infraContainer.NetworkMode() == string(namespaces.NetworkMode(specgen.Host))
hostUsers = infraContainer.IDMappings().HostUIDMapping && infraContainer.IDMappings().HostGIDMapping hostUsers = infraContainer.IDMappings().HostUIDMapping && infraContainer.IDMappings().HostGIDMapping
} }
pod, err := p.podWithContainers(ctx, allContainers, ports, hostNetwork, hostUsers, getService) pod, err := p.podWithContainers(ctx, allContainers, ports, hostNetwork, hostUsers, getService, useLongAnnotations)
if err != nil { if err != nil {
return nil, servicePorts, err return nil, servicePorts, err
} }
@ -370,9 +370,9 @@ func newServicePortState() servicePortState {
} }
} }
func TruncateKubeAnnotation(str string) string { func truncateKubeAnnotation(str string, useLongAnnotations bool) string {
str = strings.TrimSpace(str) str = strings.TrimSpace(str)
if utf8.RuneCountInString(str) < define.MaxKubeAnnotation { if useLongAnnotations || utf8.RuneCountInString(str) < define.MaxKubeAnnotation {
return str return str
} }
trunc := string([]rune(str)[:define.MaxKubeAnnotation]) trunc := string([]rune(str)[:define.MaxKubeAnnotation])
@ -426,7 +426,7 @@ func containersToServicePorts(containers []v1.Container) ([]v1.ServicePort, erro
return sps, nil return sps, nil
} }
func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, ports []v1.ContainerPort, hostNetwork, hostUsers, getService bool) (*v1.Pod, error) { func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, ports []v1.ContainerPort, hostNetwork, hostUsers, getService, useLongAnnotations bool) (*v1.Pod, error) {
deDupPodVolumes := make(map[string]*v1.Volume) deDupPodVolumes := make(map[string]*v1.Volume)
first := true first := true
podContainers := make([]v1.Container, 0, len(containers)) podContainers := make([]v1.Container, 0, len(containers))
@ -445,11 +445,11 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
if define.IsReservedAnnotation(k) || annotations.IsReservedAnnotation(k) { if define.IsReservedAnnotation(k) || annotations.IsReservedAnnotation(k) {
continue continue
} }
podAnnotations[fmt.Sprintf("%s/%s", k, removeUnderscores(ctr.Name()))] = TruncateKubeAnnotation(v) podAnnotations[fmt.Sprintf("%s/%s", k, removeUnderscores(ctr.Name()))] = truncateKubeAnnotation(v, useLongAnnotations)
} }
// Convert auto-update labels into kube annotations // Convert auto-update labels into kube annotations
for k, v := range getAutoUpdateAnnotations(ctr.Name(), ctr.Labels()) { for k, v := range getAutoUpdateAnnotations(ctr.Name(), ctr.Labels(), useLongAnnotations) {
podAnnotations[k] = TruncateKubeAnnotation(v) podAnnotations[k] = truncateKubeAnnotation(v, useLongAnnotations)
} }
isInit := ctr.IsInitCtr() isInit := ctr.IsInitCtr()
// Since hostname is only set at pod level, set the hostname to the hostname of the first container we encounter // Since hostname is only set at pod level, set the hostname to the hostname of the first container we encounter
@ -466,7 +466,7 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
return nil, err return nil, err
} }
for k, v := range annotations { for k, v := range annotations {
podAnnotations[define.BindMountPrefix] = TruncateKubeAnnotation(k + ":" + v) podAnnotations[define.BindMountPrefix] = truncateKubeAnnotation(k+":"+v, useLongAnnotations)
} }
// Since port bindings for the pod are handled by the // Since port bindings for the pod are handled by the
// infra container, wipe them here only if we are sharing the net namespace // infra container, wipe them here only if we are sharing the net namespace
@ -574,7 +574,7 @@ func newPodObject(podName string, annotations map[string]string, initCtrs, conta
// simplePodWithV1Containers is a function used by inspect when kube yaml needs to be generated // simplePodWithV1Containers is a function used by inspect when kube yaml needs to be generated
// for a single container. we "insert" that container description in a pod. // for a single container. we "insert" that container description in a pod.
func simplePodWithV1Containers(ctx context.Context, ctrs []*Container, getService bool) (*v1.Pod, error) { func simplePodWithV1Containers(ctx context.Context, ctrs []*Container, getService, useLongAnnotations bool) (*v1.Pod, error) {
kubeCtrs := make([]v1.Container, 0, len(ctrs)) kubeCtrs := make([]v1.Container, 0, len(ctrs))
kubeInitCtrs := []v1.Container{} kubeInitCtrs := []v1.Container{}
kubeVolumes := make([]v1.Volume, 0) kubeVolumes := make([]v1.Volume, 0)
@ -591,12 +591,12 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container, getServic
if define.IsReservedAnnotation(k) || annotations.IsReservedAnnotation(k) { if define.IsReservedAnnotation(k) || annotations.IsReservedAnnotation(k) {
continue continue
} }
kubeAnnotations[fmt.Sprintf("%s/%s", k, removeUnderscores(ctr.Name()))] = TruncateKubeAnnotation(v) kubeAnnotations[fmt.Sprintf("%s/%s", k, removeUnderscores(ctr.Name()))] = truncateKubeAnnotation(v, useLongAnnotations)
} }
// Convert auto-update labels into kube annotations // Convert auto-update labels into kube annotations
for k, v := range getAutoUpdateAnnotations(ctr.Name(), ctr.Labels()) { for k, v := range getAutoUpdateAnnotations(ctr.Name(), ctr.Labels(), useLongAnnotations) {
kubeAnnotations[k] = TruncateKubeAnnotation(v) kubeAnnotations[k] = truncateKubeAnnotation(v, useLongAnnotations)
} }
isInit := ctr.IsInitCtr() isInit := ctr.IsInitCtr()
@ -643,7 +643,7 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container, getServic
return nil, err return nil, err
} }
for k, v := range annotations { for k, v := range annotations {
kubeAnnotations[define.BindMountPrefix] = TruncateKubeAnnotation(k + ":" + v) kubeAnnotations[define.BindMountPrefix] = truncateKubeAnnotation(k+":"+v, useLongAnnotations)
} }
if isInit { if isInit {
kubeInitCtrs = append(kubeInitCtrs, kubeCtr) kubeInitCtrs = append(kubeInitCtrs, kubeCtr)
@ -1266,7 +1266,7 @@ func removeUnderscores(s string) string {
// getAutoUpdateAnnotations searches for auto-update container labels // getAutoUpdateAnnotations searches for auto-update container labels
// and returns them as kube annotations // and returns them as kube annotations
func getAutoUpdateAnnotations(ctrName string, ctrLabels map[string]string) map[string]string { func getAutoUpdateAnnotations(ctrName string, ctrLabels map[string]string, useLongAnnotations bool) map[string]string {
autoUpdateLabel := "io.containers.autoupdate" autoUpdateLabel := "io.containers.autoupdate"
annotations := make(map[string]string) annotations := make(map[string]string)
@ -1276,7 +1276,7 @@ func getAutoUpdateAnnotations(ctrName string, ctrLabels map[string]string) map[s
// since labels can variate between containers within a pod, they will be // since labels can variate between containers within a pod, they will be
// identified with the container name when converted into kube annotations // identified with the container name when converted into kube annotations
kc := fmt.Sprintf("%s/%s", k, ctrName) kc := fmt.Sprintf("%s/%s", k, ctrName)
annotations[kc] = TruncateKubeAnnotation(v) annotations[kc] = truncateKubeAnnotation(v, useLongAnnotations)
} }
} }

View File

@ -93,6 +93,7 @@ func GenerateKube(w http.ResponseWriter, r *http.Request) {
Service bool `schema:"service"` Service bool `schema:"service"`
Type string `schema:"type"` Type string `schema:"type"`
Replicas int32 `schema:"replicas"` Replicas int32 `schema:"replicas"`
NoTrunc bool `schema:"noTrunc"`
}{ }{
// Defaults would go here. // Defaults would go here.
Replicas: 1, Replicas: 1,
@ -115,7 +116,12 @@ func GenerateKube(w http.ResponseWriter, r *http.Request) {
} }
containerEngine := abi.ContainerEngine{Libpod: runtime} containerEngine := abi.ContainerEngine{Libpod: runtime}
options := entities.GenerateKubeOptions{Service: query.Service, Type: generateType, Replicas: query.Replicas} options := entities.GenerateKubeOptions{
Service: query.Service,
Type: generateType,
Replicas: query.Replicas,
UseLongAnnotations: query.NoTrunc,
}
report, err := containerEngine.GenerateKube(r.Context(), query.Names, options) report, err := containerEngine.GenerateKube(r.Context(), query.Names, options)
if err != nil { if err != nil {
utils.Error(w, http.StatusInternalServerError, fmt.Errorf("generating YAML: %w", err)) utils.Error(w, http.StatusInternalServerError, fmt.Errorf("generating YAML: %w", err))

View File

@ -29,6 +29,7 @@ func KubePlay(w http.ResponseWriter, r *http.Request) {
StaticMACs []string `schema:"staticMACs"` StaticMACs []string `schema:"staticMACs"`
NoHosts bool `schema:"noHosts"` NoHosts bool `schema:"noHosts"`
PublishPorts []string `schema:"publishPorts"` PublishPorts []string `schema:"publishPorts"`
NoTrunc bool `schema:"noTrunc"`
Wait bool `schema:"wait"` Wait bool `schema:"wait"`
ServiceContainer bool `schema:"serviceContainer"` ServiceContainer bool `schema:"serviceContainer"`
}{ }{
@ -85,21 +86,22 @@ func KubePlay(w http.ResponseWriter, r *http.Request) {
containerEngine := abi.ContainerEngine{Libpod: runtime} containerEngine := abi.ContainerEngine{Libpod: runtime}
options := entities.PlayKubeOptions{ options := entities.PlayKubeOptions{
Annotations: query.Annotations, Annotations: query.Annotations,
Authfile: authfile, Authfile: authfile,
Username: username, Username: username,
Password: password, Password: password,
Networks: query.Network, Networks: query.Network,
NoHosts: query.NoHosts, NoHosts: query.NoHosts,
Quiet: true, Quiet: true,
LogDriver: logDriver, LogDriver: logDriver,
LogOptions: query.LogOptions, LogOptions: query.LogOptions,
StaticIPs: staticIPs, StaticIPs: staticIPs,
StaticMACs: staticMACs, StaticMACs: staticMACs,
IsRemote: true, IsRemote: true,
PublishPorts: query.PublishPorts, PublishPorts: query.PublishPorts,
Wait: query.Wait, Wait: query.Wait,
ServiceContainer: query.ServiceContainer, ServiceContainer: query.ServiceContainer,
UseLongAnnotations: query.NoTrunc,
} }
if _, found := r.URL.Query()["tlsVerify"]; found { if _, found := r.URL.Query()["tlsVerify"]; found {
options.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify) options.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)

View File

@ -58,6 +58,11 @@ func (s *APIServer) registerKubeHandlers(r *mux.Router) error {
// type: boolean // type: boolean
// default: false // default: false
// description: Clean up all objects created when a SIGTERM is received or pods exit. // description: Clean up all objects created when a SIGTERM is received or pods exit.
// - in: query
// name: noTrunc
// type: boolean
// default: false
// description: use annotations that are not truncated to the Kubernetes maximum length of 63 characters
// - in: body // - in: body
// name: request // name: request
// description: Kubernetes YAML file. // description: Kubernetes YAML file.
@ -125,6 +130,11 @@ func (s *APIServer) registerKubeHandlers(r *mux.Router) error {
// format: int32 // format: int32
// default: 0 // default: 0
// description: Set the replica number for Deployment kind. // description: Set the replica number for Deployment kind.
// - in: query
// name: noTrunc
// type: boolean
// default: false
// description: don't truncate annotations to the Kubernetes maximum length of 63 characters
// produces: // produces:
// - text/vnd.yaml // - text/vnd.yaml
// - application/json // - application/json

View File

@ -10,6 +10,8 @@ type KubeOptions struct {
Type *string Type *string
// Replicas - the value to set in the replicas field for a Deployment // Replicas - the value to set in the replicas field for a Deployment
Replicas *int32 Replicas *int32
// NoTrunc - don't truncate annotations to the Kubernetes maximum length of 63 characters
NoTrunc *bool
} }
// SystemdOptions are optional options for generating systemd files // SystemdOptions are optional options for generating systemd files

View File

@ -61,3 +61,18 @@ func (o *KubeOptions) GetReplicas() int32 {
} }
return *o.Replicas return *o.Replicas
} }
// WithNoTrunc set field NoTrunc to given value
func (o *KubeOptions) WithNoTrunc(value bool) *KubeOptions {
o.NoTrunc = &value
return o
}
// GetNoTrunc returns value of field NoTrunc
func (o *KubeOptions) GetNoTrunc() bool {
if o.NoTrunc == nil {
var z bool
return z
}
return *o.NoTrunc
}

View File

@ -44,6 +44,9 @@ type PlayOptions struct {
LogOptions *[]string LogOptions *[]string
// Start - don't start the pod if false // Start - don't start the pod if false
Start *bool Start *bool
// NoTrunc - use annotations that were not truncated to the
// Kubernetes maximum of 63 characters
NoTrunc *bool
// Userns - define the user namespace to use. // Userns - define the user namespace to use.
Userns *string Userns *string
// Force - remove volumes on --down // Force - remove volumes on --down

View File

@ -273,6 +273,21 @@ func (o *PlayOptions) GetStart() bool {
return *o.Start return *o.Start
} }
// WithNoTrunc set field NoTrunc to given value
func (o *PlayOptions) WithNoTrunc(value bool) *PlayOptions {
o.NoTrunc = &value
return o
}
// GetNoTrunc returns value of field NoTrunc
func (o *PlayOptions) GetNoTrunc() bool {
if o.NoTrunc == nil {
var z bool
return z
}
return *o.NoTrunc
}
// WithUserns set field Userns to given value // WithUserns set field Userns to given value
func (o *PlayOptions) WithUserns(value string) *PlayOptions { func (o *PlayOptions) WithUserns(value string) *PlayOptions {
o.Userns = &value o.Userns = &value

View File

@ -35,6 +35,8 @@ type GenerateKubeOptions struct {
Type string Type string
// Replicas - the value to set in the replicas field for a Deployment // Replicas - the value to set in the replicas field for a Deployment
Replicas int32 Replicas int32
// UseLongAnnotations - don't truncate annotations to the Kubernetes maximum length of 63 characters
UseLongAnnotations bool
} }
type KubeGenerateOptions = GenerateKubeOptions type KubeGenerateOptions = GenerateKubeOptions

View File

@ -59,6 +59,9 @@ type PlayKubeOptions struct {
Start types.OptionalBool Start types.OptionalBool
// ServiceContainer - creates a service container that is started before and is stopped after all pods. // ServiceContainer - creates a service container that is started before and is stopped after all pods.
ServiceContainer bool ServiceContainer bool
// UseLongAnnotations - use annotations that were not truncated to the
// Kubernetes maximum length of 63 characters
UseLongAnnotations bool
// Userns - define the user namespace to use. // Userns - define the user namespace to use.
Userns string Userns string
// IsRemote - was the request triggered by running podman-remote // IsRemote - was the request triggered by running podman-remote

View File

@ -207,7 +207,7 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string,
// Generate the kube pods from containers. // Generate the kube pods from containers.
if len(ctrs) >= 1 { if len(ctrs) >= 1 {
po, err := libpod.GenerateForKube(ctx, ctrs, options.Service) po, err := libpod.GenerateForKube(ctx, ctrs, options.Service, options.UseLongAnnotations)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -273,7 +273,7 @@ func getKubePods(ctx context.Context, pods []*libpod.Pod, options entities.Gener
svcs := [][]byte{} svcs := [][]byte{}
for _, p := range pods { for _, p := range pods {
po, sp, err := p.GenerateForKube(ctx, options.Service) po, sp, err := p.GenerateForKube(ctx, options.Service, options.UseLongAnnotations)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -229,8 +229,8 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
podTemplateSpec.ObjectMeta = podYAML.ObjectMeta podTemplateSpec.ObjectMeta = podYAML.ObjectMeta
podTemplateSpec.Spec = podYAML.Spec podTemplateSpec.Spec = podYAML.Spec
for name, val := range podYAML.Annotations { for name, val := range podYAML.Annotations {
if len(val) > define.MaxKubeAnnotation { if len(val) > define.MaxKubeAnnotation && !options.UseLongAnnotations {
return nil, fmt.Errorf("invalid annotation %q=%q value length exceeds Kubernetetes max %d", name, val, define.MaxKubeAnnotation) return nil, fmt.Errorf("annotation %q=%q value length exceeds Kubernetes max %d", name, val, define.MaxKubeAnnotation)
} }
} }
for name, val := range options.Annotations { for name, val := range options.Annotations {

View File

@ -46,7 +46,7 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string,
// //
// Note: Caller is responsible for closing returned Reader // Note: Caller is responsible for closing returned Reader
func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, opts entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) { func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, opts entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) {
options := new(generate.KubeOptions).WithService(opts.Service).WithType(opts.Type).WithReplicas(opts.Replicas) options := new(generate.KubeOptions).WithService(opts.Service).WithType(opts.Type).WithReplicas(opts.Replicas).WithNoTrunc(opts.UseLongAnnotations)
return generate.Kube(ic.ClientCtx, nameOrIDs, options) return generate.Kube(ic.ClientCtx, nameOrIDs, options)
} }
@ -73,6 +73,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, opts en
options.WithStart(start == types.OptionalBoolTrue) options.WithStart(start == types.OptionalBoolTrue)
} }
options.WithPublishPorts(opts.PublishPorts) options.WithPublishPorts(opts.PublishPorts)
options.WithNoTrunc(opts.UseLongAnnotations)
return play.KubeWithBody(ic.ClientCtx, body, options) return play.KubeWithBody(ic.ClientCtx, body, options)
} }

View File

@ -1559,4 +1559,102 @@ USER test1`
Expect(pod.Name).To(Equal("testpod")) Expect(pod.Name).To(Equal("testpod"))
Expect(pod.Spec.Hostname).To(Equal("")) Expect(pod.Spec.Hostname).To(Equal(""))
}) })
It("podman kube generate --no-trunc on container with long annotation", func() {
ctrName := "demo"
vol1 := filepath.Join(podmanTest.TempDir, RandomString(99))
err := os.MkdirAll(vol1, 0755)
Expect(err).ToNot(HaveOccurred())
session := podmanTest.Podman([]string{"create", "-v", vol1 + ":/tmp/foo:Z", "--name", ctrName, ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
kube := podmanTest.Podman([]string{"kube", "generate", "--no-trunc", ctrName})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
pod := new(v1.Pod)
err = yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).ToNot(HaveOccurred())
Expect(pod.Annotations).To(HaveKeyWithValue(define.BindMountPrefix, vol1+":Z"))
Expect(pod.Annotations).To(Not(HaveKeyWithValue(define.BindMountPrefix, vol1[:define.MaxKubeAnnotation])))
})
It("podman kube generate on container with long annotation", func() {
ctrName := "demo"
vol1 := filepath.Join(podmanTest.TempDir, RandomString(99))
err := os.MkdirAll(vol1, 0755)
Expect(err).ToNot(HaveOccurred())
session := podmanTest.Podman([]string{"create", "-v", vol1 + ":/tmp/foo:Z", "--name", ctrName, ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
kube := podmanTest.Podman([]string{"kube", "generate", ctrName})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
pod := new(v1.Pod)
err = yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).ToNot(HaveOccurred())
Expect(pod.Annotations).To(HaveKeyWithValue(define.BindMountPrefix, vol1[:define.MaxKubeAnnotation]))
Expect(pod.Annotations).To(Not(HaveKeyWithValue(define.BindMountPrefix, vol1+":Z")))
})
It("podman kube generate --no-trunc on pod with long annotation", func() {
ctrName := "demoCtr"
podName := "demoPod"
vol1 := filepath.Join(podmanTest.TempDir, RandomString(99))
err := os.MkdirAll(vol1, 0755)
Expect(err).ToNot(HaveOccurred())
session := podmanTest.Podman([]string{"pod", "create", podName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"create", "-v", vol1 + ":/tmp/foo:Z", "--name", ctrName, "--pod", podName, ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
kube := podmanTest.Podman([]string{"kube", "generate", "--no-trunc", podName})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
pod := new(v1.Pod)
err = yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).ToNot(HaveOccurred())
Expect(pod.Annotations).To(HaveKeyWithValue(define.BindMountPrefix, vol1+":Z"))
Expect(pod.Annotations).To(Not(HaveKeyWithValue(define.BindMountPrefix, vol1[:define.MaxKubeAnnotation])))
})
It("podman kube generate on pod with long annotation", func() {
ctrName := "demoCtr"
podName := "demoPod"
vol1 := filepath.Join(podmanTest.TempDir, RandomString(99))
err := os.MkdirAll(vol1, 0755)
Expect(err).ToNot(HaveOccurred())
session := podmanTest.Podman([]string{"pod", "create", podName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"create", "-v", vol1 + ":/tmp/foo:Z", "--name", ctrName, "--pod", podName, ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
kube := podmanTest.Podman([]string{"kube", "generate", podName})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
pod := new(v1.Pod)
err = yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).ToNot(HaveOccurred())
Expect(pod.Annotations).To(HaveKeyWithValue(define.BindMountPrefix, vol1[:define.MaxKubeAnnotation]))
Expect(pod.Annotations).To(Not(HaveKeyWithValue(define.BindMountPrefix, vol1+":Z")))
})
}) })

View File

@ -5341,4 +5341,44 @@ spec:
Expect(kube).Should(Exit(125)) Expect(kube).Should(Exit(125))
Expect(kube.ErrorToString()).To(ContainSubstring("since Network Namespace set to host: invalid argument")) Expect(kube.ErrorToString()).To(ContainSubstring("since Network Namespace set to host: invalid argument"))
}) })
It("podman kube play test with --no-trunc", func() {
ctrName := "demo"
vol1 := filepath.Join(podmanTest.TempDir, RandomString(99))
err := os.MkdirAll(vol1, 0755)
Expect(err).ToNot(HaveOccurred())
session := podmanTest.Podman([]string{"run", "-v", vol1 + ":/tmp/foo:Z", "--name", ctrName, ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
file := filepath.Join(podmanTest.TempDir, ctrName+".yml")
session = podmanTest.Podman([]string{"kube", "generate", "--no-trunc", "-f", file, ctrName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"kube", "play", "--no-trunc", file})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
})
It("podman kube play test with long annotation", func() {
ctrName := "demo"
vol1 := filepath.Join(podmanTest.TempDir, RandomString(99))
err := os.MkdirAll(vol1, 0755)
Expect(err).ToNot(HaveOccurred())
session := podmanTest.Podman([]string{"run", "-v", vol1 + ":/tmp/foo:Z", "--name", ctrName, ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
file := filepath.Join(podmanTest.TempDir, ctrName+".yml")
session = podmanTest.Podman([]string{"kube", "generate", "--no-trunc", "-f", file, ctrName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"kube", "play", file})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(125))
})
}) })

View File

@ -431,12 +431,27 @@ _EOF
assert "$output" =~ "annotation exceeds maximum size, 63, of kubernetes annotation:" "Expected to fail with Length greater than 63" assert "$output" =~ "annotation exceeds maximum size, 63, of kubernetes annotation:" "Expected to fail with Length greater than 63"
} }
@test "podman play --no-trunc --annotation > Max" {
TESTDIR=$PODMAN_TMPDIR/testdir
RANDOMSTRING=$(random_string 65)
mkdir -p $TESTDIR
echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
run_podman play kube --no-trunc --annotation "name=$RANDOMSTRING" $PODMAN_TMPDIR/test.yaml
}
@test "podman play Yaml with annotation > Max" { @test "podman play Yaml with annotation > Max" {
RANDOMSTRING=$(random_string 65) RANDOMSTRING=$(random_string 65)
_write_test_yaml "annotations=test: ${RANDOMSTRING}" command=id _write_test_yaml "annotations=test: ${RANDOMSTRING}" command=id
run_podman 125 play kube - < $PODMAN_TMPDIR/test.yaml run_podman 125 play kube - < $PODMAN_TMPDIR/test.yaml
assert "$output" =~ "invalid annotation \"test\"=\"$RANDOMSTRING\"" "Expected to fail with annotation length greater than 63" assert "$output" =~ "annotation \"test\"=\"$RANDOMSTRING\" value length exceeds Kubernetes max 63" "Expected to fail with annotation length greater than 63"
}
@test "podman play Yaml --no-trunc with annotation > Max" {
RANDOMSTRING=$(random_string 65)
_write_test_yaml "annotations=test: ${RANDOMSTRING}" command=id
run_podman play kube --no-trunc - < $PODMAN_TMPDIR/test.yaml
} }
@test "podman kube play - default log driver" { @test "podman kube play - default log driver" {