mirror of
https://github.com/containers/podman.git
synced 2025-08-05 19:02:37 +08:00
Merge pull request #14023 from rhatdan/kube
Truncate annotations when generating kubernetes yaml files
This commit is contained in:
@ -178,7 +178,11 @@ func kube(cmd *cobra.Command, args []string) error {
|
||||
if kubeOptions.Annotations == nil {
|
||||
kubeOptions.Annotations = make(map[string]string)
|
||||
}
|
||||
kubeOptions.Annotations[splitN[0]] = splitN[1]
|
||||
annotation := splitN[1]
|
||||
if len(annotation) > define.MaxKubeAnnotation {
|
||||
return errors.Errorf("annotation exceeds maximum size, %d, of kubernetes annotation: %s", define.MaxKubeAnnotation, annotation)
|
||||
}
|
||||
kubeOptions.Annotations[splitN[0]] = annotation
|
||||
}
|
||||
yamlfile := args[0]
|
||||
if yamlfile == "-" {
|
||||
|
@ -135,6 +135,8 @@ const (
|
||||
// creating a checkpoint image to specify the name of host distribution on
|
||||
// which the checkpoint was created.
|
||||
CheckpointAnnotationDistributionName = "io.podman.annotations.checkpoint.distribution.name"
|
||||
// MaxKubeAnnotation is the max length of annotations allowed by Kubernetes.
|
||||
MaxKubeAnnotation = 63
|
||||
)
|
||||
|
||||
// IsReservedAnnotation returns true if the specified value corresponds to an
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/containers/common/libnetwork/types"
|
||||
"github.com/containers/common/pkg/config"
|
||||
@ -288,6 +289,16 @@ func newServicePortState() servicePortState {
|
||||
}
|
||||
}
|
||||
|
||||
func TruncateKubeAnnotation(str string) string {
|
||||
str = strings.TrimSpace(str)
|
||||
if utf8.RuneCountInString(str) < define.MaxKubeAnnotation {
|
||||
return str
|
||||
}
|
||||
trunc := string([]rune(str)[:define.MaxKubeAnnotation])
|
||||
logrus.Warnf("Truncation Annotation: %q to %q: Kubernetes only allows %d characters", str, trunc, define.MaxKubeAnnotation)
|
||||
return trunc
|
||||
}
|
||||
|
||||
// containerPortsToServicePorts takes a slice of containerports and generates a
|
||||
// slice of service ports
|
||||
func (state *servicePortState) containerPortsToServicePorts(containerPorts []v1.ContainerPort) ([]v1.ServicePort, error) {
|
||||
@ -348,11 +359,13 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
|
||||
|
||||
for _, ctr := range containers {
|
||||
if !ctr.IsInfra() {
|
||||
// Convert auto-update labels into kube annotations
|
||||
for k, v := range getAutoUpdateAnnotations(removeUnderscores(ctr.Name()), ctr.Labels()) {
|
||||
podAnnotations[k] = v
|
||||
for k, v := range ctr.config.Spec.Annotations {
|
||||
podAnnotations[fmt.Sprintf("%s/%s", k, removeUnderscores(ctr.Name()))] = TruncateKubeAnnotation(v)
|
||||
}
|
||||
// Convert auto-update labels into kube annotations
|
||||
for k, v := range getAutoUpdateAnnotations(ctr.Name(), ctr.Labels()) {
|
||||
podAnnotations[k] = TruncateKubeAnnotation(v)
|
||||
}
|
||||
|
||||
isInit := ctr.IsInitCtr()
|
||||
|
||||
ctr, volumes, _, annotations, err := containerToV1Container(ctx, ctr)
|
||||
@ -360,7 +373,7 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
|
||||
return nil, err
|
||||
}
|
||||
for k, v := range annotations {
|
||||
podAnnotations[define.BindMountPrefix+k] = strings.TrimSpace(v)
|
||||
podAnnotations[define.BindMountPrefix+k] = TruncateKubeAnnotation(v)
|
||||
}
|
||||
// Since port bindings for the pod are handled by the
|
||||
// infra container, wipe them here.
|
||||
@ -466,10 +479,14 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod,
|
||||
kubeAnnotations := make(map[string]string)
|
||||
ctrNames := make([]string, 0, len(ctrs))
|
||||
for _, ctr := range ctrs {
|
||||
ctrNames = append(ctrNames, strings.ReplaceAll(ctr.Name(), "_", ""))
|
||||
ctrNames = append(ctrNames, removeUnderscores(ctr.Name()))
|
||||
for k, v := range ctr.config.Spec.Annotations {
|
||||
kubeAnnotations[fmt.Sprintf("%s/%s", k, removeUnderscores(ctr.Name()))] = TruncateKubeAnnotation(v)
|
||||
}
|
||||
|
||||
// Convert auto-update labels into kube annotations
|
||||
for k, v := range getAutoUpdateAnnotations(removeUnderscores(ctr.Name()), ctr.Labels()) {
|
||||
kubeAnnotations[k] = v
|
||||
for k, v := range getAutoUpdateAnnotations(ctr.Name(), ctr.Labels()) {
|
||||
kubeAnnotations[k] = TruncateKubeAnnotation(v)
|
||||
}
|
||||
|
||||
isInit := ctr.IsInitCtr()
|
||||
@ -482,7 +499,7 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod,
|
||||
return nil, err
|
||||
}
|
||||
for k, v := range annotations {
|
||||
kubeAnnotations[define.BindMountPrefix+k] = strings.TrimSpace(v)
|
||||
kubeAnnotations[define.BindMountPrefix+k] = TruncateKubeAnnotation(v)
|
||||
}
|
||||
if isInit {
|
||||
kubeInitCtrs = append(kubeInitCtrs, kubeCtr)
|
||||
@ -523,7 +540,7 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod,
|
||||
}
|
||||
} // end if ctrDNS
|
||||
}
|
||||
podName := strings.ReplaceAll(ctrs[0].Name(), "_", "")
|
||||
podName := removeUnderscores(ctrs[0].Name())
|
||||
// Check if the pod name and container name will end up conflicting
|
||||
// Append -pod if so
|
||||
if util.StringInSlice(podName, ctrNames) {
|
||||
@ -1057,12 +1074,13 @@ func getAutoUpdateAnnotations(ctrName string, ctrLabels map[string]string) map[s
|
||||
autoUpdateLabel := "io.containers.autoupdate"
|
||||
annotations := make(map[string]string)
|
||||
|
||||
ctrName = removeUnderscores(ctrName)
|
||||
for k, v := range ctrLabels {
|
||||
if strings.Contains(k, autoUpdateLabel) {
|
||||
// since labels can variate between containers within a pod, they will be
|
||||
// identified with the container name when converted into kube annotations
|
||||
kc := fmt.Sprintf("%s/%s", k, ctrName)
|
||||
annotations[kc] = v
|
||||
annotations[kc] = TruncateKubeAnnotation(v)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,11 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
|
||||
|
||||
podTemplateSpec.ObjectMeta = podYAML.ObjectMeta
|
||||
podTemplateSpec.Spec = podYAML.Spec
|
||||
|
||||
for name, val := range podYAML.Annotations {
|
||||
if len(val) > define.MaxKubeAnnotation {
|
||||
return nil, errors.Errorf("invalid annotation %q=%q value length exceeds Kubernetetes max %d", name, val, define.MaxKubeAnnotation)
|
||||
}
|
||||
}
|
||||
for name, val := range options.Annotations {
|
||||
if podYAML.Annotations == nil {
|
||||
podYAML.Annotations = make(map[string]string)
|
||||
|
@ -12,7 +12,7 @@ type initMachine struct {
|
||||
--image-path string Path to qcow image (default "testing")
|
||||
-m, --memory uint Memory in MB (default 2048)
|
||||
--now Start machine now
|
||||
--rootful Whether this machine should prefer rootful container exectution
|
||||
--rootful Whether this machine should prefer rootful container execution
|
||||
--timezone string Set timezone (default "local")
|
||||
-v, --volume stringArray Volumes to mount, source:target
|
||||
--volume-driver string Optional volume driver
|
||||
|
@ -116,7 +116,7 @@ func teardown(origHomeDir string, testDir string, mb *machineTestBuilder) {
|
||||
s := new(stopMachine)
|
||||
for _, name := range mb.names {
|
||||
if _, err := mb.setName(name).setCmd(s).run(); err != nil {
|
||||
fmt.Printf("error occured rm'ing machine: %q\n", err)
|
||||
fmt.Printf("error occurred rm'ing machine: %q\n", err)
|
||||
}
|
||||
}
|
||||
if err := os.RemoveAll(testDir); err != nil {
|
||||
|
@ -233,3 +233,48 @@ _EOF
|
||||
run_podman stop -a -t 0
|
||||
run_podman pod rm -t 0 -f test_pod
|
||||
}
|
||||
|
||||
@test "podman play --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 125 play kube --annotation "name=$RANDOMSTRING" $PODMAN_TMPDIR/test.yaml
|
||||
assert "$output" =~ "annotation exceeds maximum size, 63, of kubernetes annotation:" "Expected to fail with Length greater than 63"
|
||||
}
|
||||
|
||||
@test "podman play Yaml with annotation > Max" {
|
||||
RANDOMSTRING=$(random_string 65)
|
||||
testBadYaml="
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
annotations:
|
||||
test: ${RANDOMSTRING}
|
||||
labels:
|
||||
app: test
|
||||
name: test_pod
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- id
|
||||
env:
|
||||
- name: PATH
|
||||
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
- name: TERM
|
||||
value: xterm
|
||||
- name: container
|
||||
|
||||
value: podman
|
||||
image: quay.io/libpod/userimage
|
||||
name: test
|
||||
resources: {}
|
||||
status: {}
|
||||
"
|
||||
TESTDIR=$PODMAN_TMPDIR/testdir
|
||||
mkdir -p $TESTDIR
|
||||
echo "$testBadYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $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"
|
||||
}
|
||||
|
Reference in New Issue
Block a user