mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 05:57:25 +00:00
Add keep options
This commit is contained in:
parent
d8ed461ba1
commit
b63fa1300c
24
hack/testdata/pod-with-metadata-and-probes.yaml
vendored
Normal file
24
hack/testdata/pod-with-metadata-and-probes.yaml
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
test: test
|
||||||
|
labels:
|
||||||
|
run: target
|
||||||
|
name: target
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: registry.k8s.io/nginx:1.7.9
|
||||||
|
name: target
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["/bin/sh", "-c", "cat probe"]
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["/bin/sh", "-c", "cat probe"]
|
||||||
|
startupProbe:
|
||||||
|
exec:
|
||||||
|
command: ["/bin/sh", "-c", "cat probe"]
|
||||||
|
initContainers:
|
||||||
|
- image: busybox
|
||||||
|
name: init
|
@ -111,29 +111,35 @@ type DebugAttachFunc func(ctx context.Context, restClientGetter genericclioption
|
|||||||
|
|
||||||
// DebugOptions holds the options for an invocation of kubectl debug.
|
// DebugOptions holds the options for an invocation of kubectl debug.
|
||||||
type DebugOptions struct {
|
type DebugOptions struct {
|
||||||
Args []string
|
Args []string
|
||||||
ArgsOnly bool
|
ArgsOnly bool
|
||||||
Attach bool
|
Attach bool
|
||||||
AttachFunc DebugAttachFunc
|
AttachFunc DebugAttachFunc
|
||||||
Container string
|
Container string
|
||||||
CopyTo string
|
CopyTo string
|
||||||
Replace bool
|
Replace bool
|
||||||
Env []corev1.EnvVar
|
Env []corev1.EnvVar
|
||||||
Image string
|
Image string
|
||||||
Interactive bool
|
Interactive bool
|
||||||
Namespace string
|
KeepLabels bool
|
||||||
TargetNames []string
|
KeepAnnotations bool
|
||||||
PullPolicy corev1.PullPolicy
|
KeepLiveness bool
|
||||||
Quiet bool
|
KeepReadiness bool
|
||||||
SameNode bool
|
KeepStartup bool
|
||||||
SetImages map[string]string
|
KeepInitContainers bool
|
||||||
ShareProcesses bool
|
Namespace string
|
||||||
TargetContainer string
|
TargetNames []string
|
||||||
TTY bool
|
PullPolicy corev1.PullPolicy
|
||||||
Profile string
|
Quiet bool
|
||||||
CustomProfileFile string
|
SameNode bool
|
||||||
CustomProfile *corev1.Container
|
SetImages map[string]string
|
||||||
Applier ProfileApplier
|
ShareProcesses bool
|
||||||
|
TargetContainer string
|
||||||
|
TTY bool
|
||||||
|
Profile string
|
||||||
|
CustomProfileFile string
|
||||||
|
CustomProfile *corev1.Container
|
||||||
|
Applier ProfileApplier
|
||||||
|
|
||||||
explicitNamespace bool
|
explicitNamespace bool
|
||||||
attachChanged bool
|
attachChanged bool
|
||||||
@ -151,10 +157,11 @@ type DebugOptions struct {
|
|||||||
// NewDebugOptions returns a DebugOptions initialized with default values.
|
// NewDebugOptions returns a DebugOptions initialized with default values.
|
||||||
func NewDebugOptions(streams genericiooptions.IOStreams) *DebugOptions {
|
func NewDebugOptions(streams genericiooptions.IOStreams) *DebugOptions {
|
||||||
return &DebugOptions{
|
return &DebugOptions{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
IOStreams: streams,
|
IOStreams: streams,
|
||||||
TargetNames: []string{},
|
KeepInitContainers: true,
|
||||||
ShareProcesses: true,
|
TargetNames: []string{},
|
||||||
|
ShareProcesses: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,6 +196,12 @@ func (o *DebugOptions) AddFlags(cmd *cobra.Command) {
|
|||||||
cmd.Flags().BoolVar(&o.Replace, "replace", o.Replace, i18n.T("When used with '--copy-to', delete the original Pod."))
|
cmd.Flags().BoolVar(&o.Replace, "replace", o.Replace, i18n.T("When used with '--copy-to', delete the original Pod."))
|
||||||
cmd.Flags().StringToString("env", nil, i18n.T("Environment variables to set in the container."))
|
cmd.Flags().StringToString("env", nil, i18n.T("Environment variables to set in the container."))
|
||||||
cmd.Flags().StringVar(&o.Image, "image", o.Image, i18n.T("Container image to use for debug container."))
|
cmd.Flags().StringVar(&o.Image, "image", o.Image, i18n.T("Container image to use for debug container."))
|
||||||
|
cmd.Flags().BoolVar(&o.KeepLabels, "keep-labels", o.KeepLabels, i18n.T("If true, keep the original pod labels.(This flag only works when used with '--copy-to')"))
|
||||||
|
cmd.Flags().BoolVar(&o.KeepAnnotations, "keep-annotations", o.KeepAnnotations, i18n.T("If true, keep the original pod annotations.(This flag only works when used with '--copy-to')"))
|
||||||
|
cmd.Flags().BoolVar(&o.KeepLiveness, "keep-liveness", o.KeepLiveness, i18n.T("If true, keep the original pod liveness probes.(This flag only works when used with '--copy-to')"))
|
||||||
|
cmd.Flags().BoolVar(&o.KeepReadiness, "keep-readiness", o.KeepReadiness, i18n.T("If true, keep the original pod readiness probes.(This flag only works when used with '--copy-to')"))
|
||||||
|
cmd.Flags().BoolVar(&o.KeepStartup, "keep-startup", o.KeepStartup, i18n.T("If true, keep the original startup probes.(This flag only works when used with '--copy-to')"))
|
||||||
|
cmd.Flags().BoolVar(&o.KeepInitContainers, "keep-init-containers", o.KeepInitContainers, i18n.T("Run the init containers for the pod. Defaults to true.(This flag only works when used with '--copy-to')"))
|
||||||
cmd.Flags().StringToStringVar(&o.SetImages, "set-image", o.SetImages, i18n.T("When used with '--copy-to', a list of name=image pairs for changing container images, similar to how 'kubectl set image' works."))
|
cmd.Flags().StringToStringVar(&o.SetImages, "set-image", o.SetImages, i18n.T("When used with '--copy-to', a list of name=image pairs for changing container images, similar to how 'kubectl set image' works."))
|
||||||
cmd.Flags().String("image-pull-policy", "", i18n.T("The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server."))
|
cmd.Flags().String("image-pull-policy", "", i18n.T("The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server."))
|
||||||
cmd.Flags().BoolVarP(&o.Interactive, "stdin", "i", o.Interactive, i18n.T("Keep stdin open on the container(s) in the pod, even if nothing is attached."))
|
cmd.Flags().BoolVarP(&o.Interactive, "stdin", "i", o.Interactive, i18n.T("Keep stdin open on the container(s) in the pod, even if nothing is attached."))
|
||||||
@ -257,7 +270,15 @@ func (o *DebugOptions) Complete(restClientGetter genericclioptions.RESTClientGet
|
|||||||
}
|
}
|
||||||
|
|
||||||
if o.Applier == nil {
|
if o.Applier == nil {
|
||||||
applier, err := NewProfileApplier(o.Profile)
|
kflags := KeepFlags{
|
||||||
|
Labels: o.KeepLabels,
|
||||||
|
Annotations: o.KeepAnnotations,
|
||||||
|
Liveness: o.KeepLiveness,
|
||||||
|
Readiness: o.KeepReadiness,
|
||||||
|
Startup: o.KeepStartup,
|
||||||
|
InitContainers: o.KeepInitContainers,
|
||||||
|
}
|
||||||
|
applier, err := NewProfileApplier(o.Profile, kflags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -708,6 +729,7 @@ func (o *DebugOptions) generatePodCopyWithDebugContainer(pod *corev1.Pod) (*core
|
|||||||
Name: o.CopyTo,
|
Name: o.CopyTo,
|
||||||
Namespace: pod.Namespace,
|
Namespace: pod.Namespace,
|
||||||
Annotations: pod.Annotations,
|
Annotations: pod.Annotations,
|
||||||
|
Labels: pod.Labels,
|
||||||
},
|
},
|
||||||
Spec: *pod.Spec.DeepCopy(),
|
Spec: *pod.Spec.DeepCopy(),
|
||||||
}
|
}
|
||||||
|
@ -339,18 +339,24 @@ func TestGenerateDebugContainer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
tc.opts.IOStreams = genericiooptions.NewTestIOStreamsDiscard()
|
var err error
|
||||||
suffixCounter = 0
|
kflags := KeepFlags{
|
||||||
|
Labels: tc.opts.KeepLabels,
|
||||||
if tc.pod == nil {
|
Annotations: tc.opts.KeepAnnotations,
|
||||||
tc.pod = &corev1.Pod{}
|
Liveness: tc.opts.KeepLiveness,
|
||||||
|
Readiness: tc.opts.KeepReadiness,
|
||||||
|
Startup: tc.opts.KeepStartup,
|
||||||
|
InitContainers: tc.opts.KeepInitContainers,
|
||||||
}
|
}
|
||||||
|
tc.opts.Applier, err = NewProfileApplier(tc.opts.Profile, kflags)
|
||||||
applier, err := NewProfileApplier(tc.opts.Profile)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create profile applier: %s: %v", tc.opts.Profile, err)
|
t.Fatalf("failed to create profile applier: %s: %v", tc.opts.Profile, err)
|
||||||
}
|
}
|
||||||
tc.opts.Applier = applier
|
tc.opts.IOStreams = genericiooptions.NewTestIOStreamsDiscard()
|
||||||
|
suffixCounter = 0
|
||||||
|
if tc.pod == nil {
|
||||||
|
tc.pod = &corev1.Pod{}
|
||||||
|
}
|
||||||
|
|
||||||
_, debugContainer, err := tc.opts.generateDebugContainer(tc.pod)
|
_, debugContainer, err := tc.opts.generateDebugContainer(tc.pod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -426,6 +432,9 @@ func TestGeneratePodCopyWithDebugContainer(t *testing.T) {
|
|||||||
havePod: &corev1.Pod{
|
havePod: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "target",
|
Name: "target",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "business",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
@ -792,13 +801,63 @@ func TestGeneratePodCopyWithDebugContainer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "pod with probes",
|
||||||
|
opts: &DebugOptions{
|
||||||
|
CopyTo: "debugger",
|
||||||
|
Container: "debugger",
|
||||||
|
Image: "busybox",
|
||||||
|
KeepLiveness: true,
|
||||||
|
KeepReadiness: true,
|
||||||
|
KeepStartup: true,
|
||||||
|
PullPolicy: corev1.PullIfNotPresent,
|
||||||
|
Profile: ProfileLegacy,
|
||||||
|
},
|
||||||
|
havePod: &corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "target",
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "business",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantPod: &corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "debugger",
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "business",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "debugger",
|
||||||
|
Image: "busybox",
|
||||||
|
ImagePullPolicy: corev1.PullIfNotPresent,
|
||||||
|
TerminationMessagePolicy: corev1.TerminationMessageReadFile,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "pod with init containers",
|
name: "pod with init containers",
|
||||||
opts: &DebugOptions{
|
opts: &DebugOptions{
|
||||||
CopyTo: "debugger",
|
CopyTo: "debugger",
|
||||||
Image: "busybox",
|
Image: "busybox",
|
||||||
PullPolicy: corev1.PullIfNotPresent,
|
KeepInitContainers: true,
|
||||||
Profile: ProfileLegacy,
|
PullPolicy: corev1.PullIfNotPresent,
|
||||||
|
Profile: ProfileLegacy,
|
||||||
},
|
},
|
||||||
havePod: &corev1.Pod{
|
havePod: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -1356,7 +1415,15 @@ func TestGeneratePodCopyWithDebugContainer(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
tc.opts.Applier, err = NewProfileApplier(tc.opts.Profile)
|
kflags := KeepFlags{
|
||||||
|
Labels: tc.opts.KeepLabels,
|
||||||
|
Annotations: tc.opts.KeepAnnotations,
|
||||||
|
Liveness: tc.opts.KeepLiveness,
|
||||||
|
Readiness: tc.opts.KeepReadiness,
|
||||||
|
Startup: tc.opts.KeepStartup,
|
||||||
|
InitContainers: tc.opts.KeepInitContainers,
|
||||||
|
}
|
||||||
|
tc.opts.Applier, err = NewProfileApplier(tc.opts.Profile, kflags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Fail to create profile applier: %s: %v", tc.opts.Profile, err)
|
t.Fatalf("Fail to create profile applier: %s: %v", tc.opts.Profile, err)
|
||||||
}
|
}
|
||||||
@ -1739,7 +1806,15 @@ func TestGenerateNodeDebugPod(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
tc.opts.Applier, err = NewProfileApplier(tc.opts.Profile)
|
kflags := KeepFlags{
|
||||||
|
Labels: tc.opts.KeepLabels,
|
||||||
|
Annotations: tc.opts.KeepAnnotations,
|
||||||
|
Liveness: tc.opts.KeepLiveness,
|
||||||
|
Readiness: tc.opts.KeepReadiness,
|
||||||
|
Startup: tc.opts.KeepStartup,
|
||||||
|
InitContainers: tc.opts.KeepInitContainers,
|
||||||
|
}
|
||||||
|
tc.opts.Applier, err = NewProfileApplier(tc.opts.Profile, kflags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Fail to create profile applier: %s: %v", tc.opts.Profile, err)
|
t.Fatalf("Fail to create profile applier: %s: %v", tc.opts.Profile, err)
|
||||||
}
|
}
|
||||||
@ -2015,7 +2090,15 @@ func TestGenerateNodeDebugPodCustomProfile(t *testing.T) {
|
|||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
cmdtesting.WithAlphaEnvs([]cmdutil.FeatureGate{cmdutil.DebugCustomProfile}, t, func(t *testing.T) {
|
cmdtesting.WithAlphaEnvs([]cmdutil.FeatureGate{cmdutil.DebugCustomProfile}, t, func(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
tc.opts.Applier, err = NewProfileApplier(tc.opts.Profile)
|
kflags := KeepFlags{
|
||||||
|
Labels: tc.opts.KeepLabels,
|
||||||
|
Annotations: tc.opts.KeepAnnotations,
|
||||||
|
Liveness: tc.opts.KeepLiveness,
|
||||||
|
Readiness: tc.opts.KeepReadiness,
|
||||||
|
Startup: tc.opts.KeepStartup,
|
||||||
|
InitContainers: tc.opts.KeepInitContainers,
|
||||||
|
}
|
||||||
|
tc.opts.Applier, err = NewProfileApplier(tc.opts.Profile, kflags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Fail to create profile applier: %s: %v", tc.opts.Profile, err)
|
t.Fatalf("Fail to create profile applier: %s: %v", tc.opts.Profile, err)
|
||||||
}
|
}
|
||||||
@ -2215,7 +2298,15 @@ func TestGenerateCopyDebugPodCustomProfile(t *testing.T) {
|
|||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
cmdtesting.WithAlphaEnvs([]cmdutil.FeatureGate{cmdutil.DebugCustomProfile}, t, func(t *testing.T) {
|
cmdtesting.WithAlphaEnvs([]cmdutil.FeatureGate{cmdutil.DebugCustomProfile}, t, func(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
tc.opts.Applier, err = NewProfileApplier(tc.opts.Profile)
|
kflags := KeepFlags{
|
||||||
|
Labels: tc.opts.KeepLabels,
|
||||||
|
Annotations: tc.opts.KeepAnnotations,
|
||||||
|
Liveness: tc.opts.KeepLiveness,
|
||||||
|
Readiness: tc.opts.KeepReadiness,
|
||||||
|
Startup: tc.opts.KeepStartup,
|
||||||
|
InitContainers: tc.opts.KeepInitContainers,
|
||||||
|
}
|
||||||
|
tc.opts.Applier, err = NewProfileApplier(tc.opts.Profile, kflags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Fail to create profile applier: %s: %v", tc.opts.Profile, err)
|
t.Fatalf("Fail to create profile applier: %s: %v", tc.opts.Profile, err)
|
||||||
}
|
}
|
||||||
@ -2421,7 +2512,15 @@ func TestGenerateEphemeralDebugPodCustomProfile(t *testing.T) {
|
|||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
cmdtesting.WithAlphaEnvs([]cmdutil.FeatureGate{cmdutil.DebugCustomProfile}, t, func(t *testing.T) {
|
cmdtesting.WithAlphaEnvs([]cmdutil.FeatureGate{cmdutil.DebugCustomProfile}, t, func(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
tc.opts.Applier, err = NewProfileApplier(tc.opts.Profile)
|
kflags := KeepFlags{
|
||||||
|
Labels: tc.opts.KeepLabels,
|
||||||
|
Annotations: tc.opts.KeepAnnotations,
|
||||||
|
Liveness: tc.opts.KeepLiveness,
|
||||||
|
Readiness: tc.opts.KeepReadiness,
|
||||||
|
Startup: tc.opts.KeepStartup,
|
||||||
|
InitContainers: tc.opts.KeepInitContainers,
|
||||||
|
}
|
||||||
|
tc.opts.Applier, err = NewProfileApplier(tc.opts.Profile, kflags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Fail to create profile applier: %s: %v", tc.opts.Profile, err)
|
t.Fatalf("Fail to create profile applier: %s: %v", tc.opts.Profile, err)
|
||||||
}
|
}
|
||||||
@ -2486,94 +2585,101 @@ func TestCompleteAndValidate(t *testing.T) {
|
|||||||
name: "Set image pull policy",
|
name: "Set image pull policy",
|
||||||
args: "--image=busybox --image-pull-policy=Always mypod",
|
args: "--image=busybox --image-pull-policy=Always mypod",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
Image: "busybox",
|
Image: "busybox",
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
PullPolicy: corev1.PullPolicy("Always"),
|
Namespace: "test",
|
||||||
ShareProcesses: true,
|
PullPolicy: corev1.PullPolicy("Always"),
|
||||||
Profile: ProfileLegacy,
|
ShareProcesses: true,
|
||||||
TargetNames: []string{"mypod"},
|
Profile: ProfileLegacy,
|
||||||
|
TargetNames: []string{"mypod"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Multiple targets",
|
name: "Multiple targets",
|
||||||
args: "--image=busybox mypod1 mypod2",
|
args: "--image=busybox mypod1 mypod2",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
Image: "busybox",
|
Image: "busybox",
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
ShareProcesses: true,
|
Namespace: "test",
|
||||||
Profile: ProfileLegacy,
|
ShareProcesses: true,
|
||||||
TargetNames: []string{"mypod1", "mypod2"},
|
Profile: ProfileLegacy,
|
||||||
|
TargetNames: []string{"mypod1", "mypod2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Arguments with dash",
|
name: "Arguments with dash",
|
||||||
args: "--image=busybox mypod1 mypod2 -- echo 1 2",
|
args: "--image=busybox mypod1 mypod2 -- echo 1 2",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{"echo", "1", "2"},
|
Args: []string{"echo", "1", "2"},
|
||||||
Image: "busybox",
|
Image: "busybox",
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
ShareProcesses: true,
|
Namespace: "test",
|
||||||
Profile: ProfileLegacy,
|
ShareProcesses: true,
|
||||||
TargetNames: []string{"mypod1", "mypod2"},
|
Profile: ProfileLegacy,
|
||||||
|
TargetNames: []string{"mypod1", "mypod2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Interactive no attach",
|
name: "Interactive no attach",
|
||||||
args: "-ti --image=busybox --attach=false mypod",
|
args: "-ti --image=busybox --attach=false mypod",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
Attach: false,
|
Attach: false,
|
||||||
Image: "busybox",
|
Image: "busybox",
|
||||||
Interactive: true,
|
KeepInitContainers: true,
|
||||||
Namespace: "test",
|
Interactive: true,
|
||||||
ShareProcesses: true,
|
Namespace: "test",
|
||||||
Profile: ProfileLegacy,
|
ShareProcesses: true,
|
||||||
TargetNames: []string{"mypod"},
|
Profile: ProfileLegacy,
|
||||||
TTY: true,
|
TargetNames: []string{"mypod"},
|
||||||
|
TTY: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Set environment variables",
|
name: "Set environment variables",
|
||||||
args: "--image=busybox --env=FOO=BAR mypod",
|
args: "--image=busybox --env=FOO=BAR mypod",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
Env: []corev1.EnvVar{{Name: "FOO", Value: "BAR"}},
|
Env: []corev1.EnvVar{{Name: "FOO", Value: "BAR"}},
|
||||||
Image: "busybox",
|
Image: "busybox",
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
ShareProcesses: true,
|
Namespace: "test",
|
||||||
Profile: ProfileLegacy,
|
ShareProcesses: true,
|
||||||
TargetNames: []string{"mypod"},
|
Profile: ProfileLegacy,
|
||||||
|
TargetNames: []string{"mypod"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Ephemeral container: interactive session minimal args",
|
name: "Ephemeral container: interactive session minimal args",
|
||||||
args: "mypod -it --image=busybox",
|
args: "mypod -it --image=busybox",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
Attach: true,
|
Attach: true,
|
||||||
Image: "busybox",
|
Image: "busybox",
|
||||||
Interactive: true,
|
Interactive: true,
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
ShareProcesses: true,
|
Namespace: "test",
|
||||||
Profile: ProfileLegacy,
|
ShareProcesses: true,
|
||||||
TargetNames: []string{"mypod"},
|
Profile: ProfileLegacy,
|
||||||
TTY: true,
|
TargetNames: []string{"mypod"},
|
||||||
|
TTY: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Ephemeral container: non-interactive debugger with image and name",
|
name: "Ephemeral container: non-interactive debugger with image and name",
|
||||||
args: "--image=myproj/debug-tools --image-pull-policy=Always -c debugger mypod",
|
args: "--image=myproj/debug-tools --image-pull-policy=Always -c debugger mypod",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
Container: "debugger",
|
Container: "debugger",
|
||||||
Image: "myproj/debug-tools",
|
Image: "myproj/debug-tools",
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
PullPolicy: corev1.PullPolicy("Always"),
|
Namespace: "test",
|
||||||
Profile: ProfileLegacy,
|
PullPolicy: corev1.PullPolicy("Always"),
|
||||||
ShareProcesses: true,
|
Profile: ProfileLegacy,
|
||||||
TargetNames: []string{"mypod"},
|
ShareProcesses: true,
|
||||||
|
TargetNames: []string{"mypod"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2605,67 +2711,72 @@ func TestCompleteAndValidate(t *testing.T) {
|
|||||||
name: "Pod copy: interactive debug container minimal args",
|
name: "Pod copy: interactive debug container minimal args",
|
||||||
args: "mypod -it --image=busybox --copy-to=my-debugger",
|
args: "mypod -it --image=busybox --copy-to=my-debugger",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
Attach: true,
|
Attach: true,
|
||||||
CopyTo: "my-debugger",
|
CopyTo: "my-debugger",
|
||||||
Image: "busybox",
|
Image: "busybox",
|
||||||
Interactive: true,
|
Interactive: true,
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
ShareProcesses: true,
|
Namespace: "test",
|
||||||
Profile: ProfileLegacy,
|
ShareProcesses: true,
|
||||||
TargetNames: []string{"mypod"},
|
Profile: ProfileLegacy,
|
||||||
TTY: true,
|
TargetNames: []string{"mypod"},
|
||||||
|
TTY: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Pod copy: non-interactive with debug container, image name and command",
|
name: "Pod copy: non-interactive with debug container, image name and command",
|
||||||
args: "mypod --image=busybox --container=my-container --copy-to=my-debugger -- sleep 1d",
|
args: "mypod --image=busybox --container=my-container --copy-to=my-debugger -- sleep 1d",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{"sleep", "1d"},
|
Args: []string{"sleep", "1d"},
|
||||||
Container: "my-container",
|
Container: "my-container",
|
||||||
CopyTo: "my-debugger",
|
CopyTo: "my-debugger",
|
||||||
Image: "busybox",
|
Image: "busybox",
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
ShareProcesses: true,
|
Namespace: "test",
|
||||||
Profile: ProfileLegacy,
|
ShareProcesses: true,
|
||||||
TargetNames: []string{"mypod"},
|
Profile: ProfileLegacy,
|
||||||
|
TargetNames: []string{"mypod"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Pod copy: explicit attach",
|
name: "Pod copy: explicit attach",
|
||||||
args: "mypod --image=busybox --copy-to=my-debugger --attach -- sleep 1d",
|
args: "mypod --image=busybox --copy-to=my-debugger --attach -- sleep 1d",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{"sleep", "1d"},
|
Args: []string{"sleep", "1d"},
|
||||||
Attach: true,
|
Attach: true,
|
||||||
CopyTo: "my-debugger",
|
CopyTo: "my-debugger",
|
||||||
Image: "busybox",
|
Image: "busybox",
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
ShareProcesses: true,
|
Namespace: "test",
|
||||||
Profile: ProfileLegacy,
|
ShareProcesses: true,
|
||||||
TargetNames: []string{"mypod"},
|
Profile: ProfileLegacy,
|
||||||
|
TargetNames: []string{"mypod"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Pod copy: replace single image of existing container",
|
name: "Pod copy: replace single image of existing container",
|
||||||
args: "mypod --image=busybox --container=my-container --copy-to=my-debugger",
|
args: "mypod --image=busybox --container=my-container --copy-to=my-debugger",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
Container: "my-container",
|
Container: "my-container",
|
||||||
CopyTo: "my-debugger",
|
CopyTo: "my-debugger",
|
||||||
Image: "busybox",
|
Image: "busybox",
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
ShareProcesses: true,
|
Namespace: "test",
|
||||||
Profile: ProfileLegacy,
|
ShareProcesses: true,
|
||||||
TargetNames: []string{"mypod"},
|
Profile: ProfileLegacy,
|
||||||
|
TargetNames: []string{"mypod"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Pod copy: mutate existing container images",
|
name: "Pod copy: mutate existing container images",
|
||||||
args: "mypod --set-image=*=busybox,app=app-debugger --copy-to=my-debugger",
|
args: "mypod --set-image=*=busybox,app=app-debugger --copy-to=my-debugger",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
CopyTo: "my-debugger",
|
CopyTo: "my-debugger",
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
|
Namespace: "test",
|
||||||
SetImages: map[string]string{
|
SetImages: map[string]string{
|
||||||
"*": "busybox",
|
"*": "busybox",
|
||||||
"app": "app-debugger",
|
"app": "app-debugger",
|
||||||
@ -2679,12 +2790,13 @@ func TestCompleteAndValidate(t *testing.T) {
|
|||||||
name: "Pod copy: add container and also mutate images",
|
name: "Pod copy: add container and also mutate images",
|
||||||
args: "mypod -it --copy-to=my-debugger --image=debian --set-image=app=app:debug,sidecar=sidecar:debug",
|
args: "mypod -it --copy-to=my-debugger --image=debian --set-image=app=app:debug,sidecar=sidecar:debug",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
Attach: true,
|
Attach: true,
|
||||||
CopyTo: "my-debugger",
|
CopyTo: "my-debugger",
|
||||||
Image: "debian",
|
Image: "debian",
|
||||||
Interactive: true,
|
Interactive: true,
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
|
Namespace: "test",
|
||||||
SetImages: map[string]string{
|
SetImages: map[string]string{
|
||||||
"app": "app:debug",
|
"app": "app:debug",
|
||||||
"sidecar": "sidecar:debug",
|
"sidecar": "sidecar:debug",
|
||||||
@ -2699,16 +2811,39 @@ func TestCompleteAndValidate(t *testing.T) {
|
|||||||
name: "Pod copy: change command",
|
name: "Pod copy: change command",
|
||||||
args: "mypod -it --copy-to=my-debugger --container=mycontainer -- sh",
|
args: "mypod -it --copy-to=my-debugger --container=mycontainer -- sh",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Attach: true,
|
Attach: true,
|
||||||
Args: []string{"sh"},
|
Args: []string{"sh"},
|
||||||
Container: "mycontainer",
|
Container: "mycontainer",
|
||||||
CopyTo: "my-debugger",
|
CopyTo: "my-debugger",
|
||||||
Interactive: true,
|
Interactive: true,
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
ShareProcesses: true,
|
Namespace: "test",
|
||||||
Profile: ProfileLegacy,
|
ShareProcesses: true,
|
||||||
TargetNames: []string{"mypod"},
|
Profile: ProfileLegacy,
|
||||||
TTY: true,
|
TargetNames: []string{"mypod"},
|
||||||
|
TTY: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Pod copy: change keep options from defaults",
|
||||||
|
args: "mypod -it --image=busybox --copy-to=my-debugger --keep-labels=true --keep-annotations=true --keep-liveness=true --keep-readiness=true --keep-startup=true --keep-init-containers=false",
|
||||||
|
wantOpts: &DebugOptions{
|
||||||
|
Args: []string{},
|
||||||
|
Attach: true,
|
||||||
|
CopyTo: "my-debugger",
|
||||||
|
Image: "busybox",
|
||||||
|
Interactive: true,
|
||||||
|
KeepLabels: true,
|
||||||
|
KeepAnnotations: true,
|
||||||
|
KeepLiveness: true,
|
||||||
|
KeepReadiness: true,
|
||||||
|
KeepStartup: true,
|
||||||
|
KeepInitContainers: false,
|
||||||
|
Namespace: "test",
|
||||||
|
ShareProcesses: true,
|
||||||
|
Profile: ProfileLegacy,
|
||||||
|
TargetNames: []string{"mypod"},
|
||||||
|
TTY: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2740,15 +2875,16 @@ func TestCompleteAndValidate(t *testing.T) {
|
|||||||
name: "Node: interactive session minimal args",
|
name: "Node: interactive session minimal args",
|
||||||
args: "node/mynode -it --image=busybox",
|
args: "node/mynode -it --image=busybox",
|
||||||
wantOpts: &DebugOptions{
|
wantOpts: &DebugOptions{
|
||||||
Args: []string{},
|
Args: []string{},
|
||||||
Attach: true,
|
Attach: true,
|
||||||
Image: "busybox",
|
Image: "busybox",
|
||||||
Interactive: true,
|
Interactive: true,
|
||||||
Namespace: "test",
|
KeepInitContainers: true,
|
||||||
ShareProcesses: true,
|
Namespace: "test",
|
||||||
Profile: ProfileLegacy,
|
ShareProcesses: true,
|
||||||
TargetNames: []string{"node/mynode"},
|
Profile: ProfileLegacy,
|
||||||
TTY: true,
|
TargetNames: []string{"node/mynode"},
|
||||||
|
TTY: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -64,54 +64,91 @@ type ProfileApplier interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewProfileApplier returns a new Options for the given profile name.
|
// NewProfileApplier returns a new Options for the given profile name.
|
||||||
func NewProfileApplier(profile string) (ProfileApplier, error) {
|
func NewProfileApplier(profile string, kflags KeepFlags) (ProfileApplier, error) {
|
||||||
switch profile {
|
switch profile {
|
||||||
case ProfileLegacy:
|
case ProfileLegacy:
|
||||||
return &legacyProfile{}, nil
|
return &legacyProfile{kflags}, nil
|
||||||
case ProfileGeneral:
|
case ProfileGeneral:
|
||||||
return &generalProfile{}, nil
|
return &generalProfile{kflags}, nil
|
||||||
case ProfileBaseline:
|
case ProfileBaseline:
|
||||||
return &baselineProfile{}, nil
|
return &baselineProfile{kflags}, nil
|
||||||
case ProfileRestricted:
|
case ProfileRestricted:
|
||||||
return &restrictedProfile{}, nil
|
return &restrictedProfile{kflags}, nil
|
||||||
case ProfileNetadmin:
|
case ProfileNetadmin:
|
||||||
return &netadminProfile{}, nil
|
return &netadminProfile{kflags}, nil
|
||||||
case ProfileSysadmin:
|
case ProfileSysadmin:
|
||||||
return &sysadminProfile{}, nil
|
return &sysadminProfile{kflags}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("unknown profile: %s", profile)
|
return nil, fmt.Errorf("unknown profile: %s", profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
type legacyProfile struct {
|
type legacyProfile struct {
|
||||||
|
KeepFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
type generalProfile struct {
|
type generalProfile struct {
|
||||||
|
KeepFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
type baselineProfile struct {
|
type baselineProfile struct {
|
||||||
|
KeepFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
type restrictedProfile struct {
|
type restrictedProfile struct {
|
||||||
|
KeepFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
type netadminProfile struct {
|
type netadminProfile struct {
|
||||||
|
KeepFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
type sysadminProfile struct {
|
type sysadminProfile struct {
|
||||||
|
KeepFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *legacyProfile) Apply(pod *corev1.Pod, containerName string, target runtime.Object) error {
|
// KeepFlags holds the flag set that determine which fields to keep in the copy pod.
|
||||||
switch target.(type) {
|
type KeepFlags struct {
|
||||||
case *corev1.Pod:
|
Labels bool
|
||||||
// do nothing to the copied pod
|
Annotations bool
|
||||||
return nil
|
Liveness bool
|
||||||
case *corev1.Node:
|
Readiness bool
|
||||||
mountRootPartition(pod, containerName)
|
Startup bool
|
||||||
useHostNamespaces(pod)
|
InitContainers bool
|
||||||
return nil
|
}
|
||||||
default:
|
|
||||||
return fmt.Errorf("the %s profile doesn't support objects of type %T", ProfileLegacy, target)
|
// RemoveLabels removes labels from the pod.
|
||||||
|
func (kflags KeepFlags) RemoveLabels(p *corev1.Pod) {
|
||||||
|
if !kflags.Labels {
|
||||||
|
p.Labels = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAnnotations remove annotations from the pod.
|
||||||
|
func (kflags KeepFlags) RemoveAnnotations(p *corev1.Pod) {
|
||||||
|
if !kflags.Annotations {
|
||||||
|
p.Annotations = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveProbes remove probes from all containers of the pod.
|
||||||
|
func (kflags KeepFlags) RemoveProbes(p *corev1.Pod) {
|
||||||
|
for i := range p.Spec.Containers {
|
||||||
|
if !kflags.Liveness {
|
||||||
|
p.Spec.Containers[i].LivenessProbe = nil
|
||||||
|
}
|
||||||
|
if !kflags.Readiness {
|
||||||
|
p.Spec.Containers[i].ReadinessProbe = nil
|
||||||
|
}
|
||||||
|
if !kflags.Startup {
|
||||||
|
p.Spec.Containers[i].StartupProbe = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveInitContainers remove initContainers from the pod.
|
||||||
|
func (kflags KeepFlags) RemoveInitContainers(p *corev1.Pod) {
|
||||||
|
if !kflags.InitContainers {
|
||||||
|
p.Spec.InitContainers = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,10 +167,32 @@ func getDebugStyle(pod *corev1.Pod, target runtime.Object) (debugStyle, error) {
|
|||||||
return unsupported, fmt.Errorf("objects of type %T are not supported", target)
|
return unsupported, fmt.Errorf("objects of type %T are not supported", target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *legacyProfile) Apply(pod *corev1.Pod, containerName string, target runtime.Object) error {
|
||||||
|
style, err := getDebugStyle(pod, target)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("legacy profile: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch style {
|
||||||
|
case node:
|
||||||
|
mountRootPartition(pod, containerName)
|
||||||
|
useHostNamespaces(pod)
|
||||||
|
|
||||||
|
case podCopy:
|
||||||
|
p.Labels = false
|
||||||
|
p.RemoveLabels(pod)
|
||||||
|
|
||||||
|
case ephemeral:
|
||||||
|
// no additional modifications needed
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *generalProfile) Apply(pod *corev1.Pod, containerName string, target runtime.Object) error {
|
func (p *generalProfile) Apply(pod *corev1.Pod, containerName string, target runtime.Object) error {
|
||||||
style, err := getDebugStyle(pod, target)
|
style, err := getDebugStyle(pod, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("general profile: %s", err)
|
return fmt.Errorf("general profile: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch style {
|
switch style {
|
||||||
@ -143,7 +202,10 @@ func (p *generalProfile) Apply(pod *corev1.Pod, containerName string, target run
|
|||||||
useHostNamespaces(pod)
|
useHostNamespaces(pod)
|
||||||
|
|
||||||
case podCopy:
|
case podCopy:
|
||||||
removeLabelsAndProbes(pod)
|
p.RemoveLabels(pod)
|
||||||
|
p.RemoveAnnotations(pod)
|
||||||
|
p.RemoveProbes(pod)
|
||||||
|
p.RemoveInitContainers(pod)
|
||||||
allowProcessTracing(pod, containerName)
|
allowProcessTracing(pod, containerName)
|
||||||
shareProcessNamespace(pod)
|
shareProcessNamespace(pod)
|
||||||
|
|
||||||
@ -157,14 +219,17 @@ func (p *generalProfile) Apply(pod *corev1.Pod, containerName string, target run
|
|||||||
func (p *baselineProfile) Apply(pod *corev1.Pod, containerName string, target runtime.Object) error {
|
func (p *baselineProfile) Apply(pod *corev1.Pod, containerName string, target runtime.Object) error {
|
||||||
style, err := getDebugStyle(pod, target)
|
style, err := getDebugStyle(pod, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("baseline profile: %s", err)
|
return fmt.Errorf("baseline profile: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
clearSecurityContext(pod, containerName)
|
clearSecurityContext(pod, containerName)
|
||||||
|
|
||||||
switch style {
|
switch style {
|
||||||
case podCopy:
|
case podCopy:
|
||||||
removeLabelsAndProbes(pod)
|
p.RemoveLabels(pod)
|
||||||
|
p.RemoveAnnotations(pod)
|
||||||
|
p.RemoveProbes(pod)
|
||||||
|
p.RemoveInitContainers(pod)
|
||||||
shareProcessNamespace(pod)
|
shareProcessNamespace(pod)
|
||||||
|
|
||||||
case ephemeral, node:
|
case ephemeral, node:
|
||||||
@ -177,7 +242,7 @@ func (p *baselineProfile) Apply(pod *corev1.Pod, containerName string, target ru
|
|||||||
func (p *restrictedProfile) Apply(pod *corev1.Pod, containerName string, target runtime.Object) error {
|
func (p *restrictedProfile) Apply(pod *corev1.Pod, containerName string, target runtime.Object) error {
|
||||||
style, err := getDebugStyle(pod, target)
|
style, err := getDebugStyle(pod, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("restricted profile: %s", err)
|
return fmt.Errorf("restricted profile: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
clearSecurityContext(pod, containerName)
|
clearSecurityContext(pod, containerName)
|
||||||
@ -188,6 +253,10 @@ func (p *restrictedProfile) Apply(pod *corev1.Pod, containerName string, target
|
|||||||
|
|
||||||
switch style {
|
switch style {
|
||||||
case podCopy:
|
case podCopy:
|
||||||
|
p.RemoveLabels(pod)
|
||||||
|
p.RemoveAnnotations(pod)
|
||||||
|
p.RemoveProbes(pod)
|
||||||
|
p.RemoveInitContainers(pod)
|
||||||
shareProcessNamespace(pod)
|
shareProcessNamespace(pod)
|
||||||
|
|
||||||
case ephemeral, node:
|
case ephemeral, node:
|
||||||
@ -200,7 +269,7 @@ func (p *restrictedProfile) Apply(pod *corev1.Pod, containerName string, target
|
|||||||
func (p *netadminProfile) Apply(pod *corev1.Pod, containerName string, target runtime.Object) error {
|
func (p *netadminProfile) Apply(pod *corev1.Pod, containerName string, target runtime.Object) error {
|
||||||
style, err := getDebugStyle(pod, target)
|
style, err := getDebugStyle(pod, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("netadmin profile: %s", err)
|
return fmt.Errorf("netadmin profile: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
allowNetadminCapability(pod, containerName)
|
allowNetadminCapability(pod, containerName)
|
||||||
@ -210,6 +279,10 @@ func (p *netadminProfile) Apply(pod *corev1.Pod, containerName string, target ru
|
|||||||
useHostNamespaces(pod)
|
useHostNamespaces(pod)
|
||||||
|
|
||||||
case podCopy:
|
case podCopy:
|
||||||
|
p.RemoveLabels(pod)
|
||||||
|
p.RemoveAnnotations(pod)
|
||||||
|
p.RemoveProbes(pod)
|
||||||
|
p.RemoveInitContainers(pod)
|
||||||
shareProcessNamespace(pod)
|
shareProcessNamespace(pod)
|
||||||
|
|
||||||
case ephemeral:
|
case ephemeral:
|
||||||
@ -222,7 +295,7 @@ func (p *netadminProfile) Apply(pod *corev1.Pod, containerName string, target ru
|
|||||||
func (p *sysadminProfile) Apply(pod *corev1.Pod, containerName string, target runtime.Object) error {
|
func (p *sysadminProfile) Apply(pod *corev1.Pod, containerName string, target runtime.Object) error {
|
||||||
style, err := getDebugStyle(pod, target)
|
style, err := getDebugStyle(pod, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("sysadmin profile: %s", err)
|
return fmt.Errorf("sysadmin profile: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
setPrivileged(pod, containerName)
|
setPrivileged(pod, containerName)
|
||||||
@ -234,7 +307,12 @@ func (p *sysadminProfile) Apply(pod *corev1.Pod, containerName string, target ru
|
|||||||
|
|
||||||
case podCopy:
|
case podCopy:
|
||||||
// to mimic general, default and baseline
|
// to mimic general, default and baseline
|
||||||
|
p.RemoveLabels(pod)
|
||||||
|
p.RemoveAnnotations(pod)
|
||||||
|
p.RemoveProbes(pod)
|
||||||
|
p.RemoveInitContainers(pod)
|
||||||
shareProcessNamespace(pod)
|
shareProcessNamespace(pod)
|
||||||
|
|
||||||
case ephemeral:
|
case ephemeral:
|
||||||
// no additional modifications needed
|
// no additional modifications needed
|
||||||
}
|
}
|
||||||
@ -242,17 +320,6 @@ func (p *sysadminProfile) Apply(pod *corev1.Pod, containerName string, target ru
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// removeLabelsAndProbes removes labels from the pod and remove probes
|
|
||||||
// from all containers of the pod.
|
|
||||||
func removeLabelsAndProbes(p *corev1.Pod) {
|
|
||||||
p.Labels = nil
|
|
||||||
for i := range p.Spec.Containers {
|
|
||||||
p.Spec.Containers[i].LivenessProbe = nil
|
|
||||||
p.Spec.Containers[i].ReadinessProbe = nil
|
|
||||||
p.Spec.Containers[i].StartupProbe = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mountRootPartition mounts the host's root path at "/host" in the container.
|
// mountRootPartition mounts the host's root path at "/host" in the container.
|
||||||
func mountRootPartition(p *corev1.Pod, containerName string) {
|
func mountRootPartition(p *corev1.Pod, containerName string) {
|
||||||
const volumeName = "host-root"
|
const volumeName = "host-root"
|
||||||
|
@ -34,6 +34,203 @@ var testNode = &corev1.Node{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLegacyProfile(t *testing.T) {
|
||||||
|
pod := &corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "pod"},
|
||||||
|
Spec: corev1.PodSpec{EphemeralContainers: []corev1.EphemeralContainer{
|
||||||
|
{
|
||||||
|
EphemeralContainerCommon: corev1.EphemeralContainerCommon{
|
||||||
|
Name: "dbg", Image: "dbgimage",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := map[string]struct {
|
||||||
|
pod *corev1.Pod
|
||||||
|
containerName string
|
||||||
|
target runtime.Object
|
||||||
|
expectPod *corev1.Pod
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
"bad inputs results in error": {
|
||||||
|
pod: nil,
|
||||||
|
containerName: "dbg",
|
||||||
|
target: runtime.Object(nil),
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
"debug by ephemeral container": {
|
||||||
|
pod: pod,
|
||||||
|
containerName: "dbg",
|
||||||
|
target: pod,
|
||||||
|
expectPod: &corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "pod"},
|
||||||
|
Spec: corev1.PodSpec{EphemeralContainers: []corev1.EphemeralContainer{
|
||||||
|
{
|
||||||
|
EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "dbg", Image: "dbgimage"},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"debug by pod copy": {
|
||||||
|
pod: &corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "podcopy",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "dbg",
|
||||||
|
Image: "dbgimage",
|
||||||
|
SecurityContext: &corev1.SecurityContext{
|
||||||
|
Capabilities: &corev1.Capabilities{
|
||||||
|
Add: []corev1.Capability{"NET_ADMIN"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
containerName: "dbg",
|
||||||
|
target: &corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "podcopy",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectPod: &corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "dbg",
|
||||||
|
Image: "dbgimage",
|
||||||
|
SecurityContext: &corev1.SecurityContext{
|
||||||
|
Capabilities: &corev1.Capabilities{
|
||||||
|
Add: []corev1.Capability{"NET_ADMIN"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"debug by node": {
|
||||||
|
pod: &corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "pod"},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "dbg",
|
||||||
|
Image: "dbgimage",
|
||||||
|
SecurityContext: &corev1.SecurityContext{
|
||||||
|
Capabilities: &corev1.Capabilities{
|
||||||
|
Add: []corev1.Capability{"NET_ADMIN"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
containerName: "dbg",
|
||||||
|
target: testNode,
|
||||||
|
expectPod: &corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "pod"},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
HostNetwork: true,
|
||||||
|
HostPID: true,
|
||||||
|
HostIPC: true,
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "dbg",
|
||||||
|
Image: "dbgimage",
|
||||||
|
SecurityContext: &corev1.SecurityContext{
|
||||||
|
Capabilities: &corev1.Capabilities{
|
||||||
|
Add: []corev1.Capability{"NET_ADMIN"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VolumeMounts: []corev1.VolumeMount{
|
||||||
|
{
|
||||||
|
MountPath: "/host",
|
||||||
|
Name: "host-root",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Volumes: []corev1.Volume{
|
||||||
|
{
|
||||||
|
Name: "host-root",
|
||||||
|
VolumeSource: corev1.VolumeSource{
|
||||||
|
HostPath: &corev1.HostPathVolumeSource{Path: "/"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, test := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
applier := &legacyProfile{KeepFlags{InitContainers: true}}
|
||||||
|
err := applier.Apply(test.pod, test.containerName, test.target)
|
||||||
|
if (err != nil) != test.expectErr {
|
||||||
|
t.Fatalf("expect error: %v, got error: %v", test.expectErr, (err != nil))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(test.expectPod, test.pod); diff != "" {
|
||||||
|
t.Error("unexpected diff in generated object: (-want +got):\n", diff)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGeneralProfile(t *testing.T) {
|
func TestGeneralProfile(t *testing.T) {
|
||||||
pod := &corev1.Pod{
|
pod := &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "pod"},
|
ObjectMeta: metav1.ObjectMeta{Name: "pod"},
|
||||||
@ -81,10 +278,25 @@ func TestGeneralProfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"debug by pod copy": {
|
"debug by pod copy": {
|
||||||
pod: &corev1.Pod{
|
pod: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "podcopy",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "dbg",
|
Name: "dbg",
|
||||||
Image: "dbgimage",
|
Image: "dbgimage",
|
||||||
@ -99,16 +311,32 @@ func TestGeneralProfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
containerName: "dbg",
|
containerName: "dbg",
|
||||||
target: &corev1.Pod{
|
target: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "podcopy",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectPod: &corev1.Pod{
|
expectPod: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{Name: "app", Image: "appimage"},
|
||||||
{
|
{
|
||||||
@ -169,7 +397,8 @@ func TestGeneralProfile(t *testing.T) {
|
|||||||
|
|
||||||
for name, test := range tests {
|
for name, test := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
err := (&generalProfile{}).Apply(test.pod, test.containerName, test.target)
|
applier := &generalProfile{KeepFlags{InitContainers: true}}
|
||||||
|
err := applier.Apply(test.pod, test.containerName, test.target)
|
||||||
if (err != nil) != test.expectErr {
|
if (err != nil) != test.expectErr {
|
||||||
t.Fatalf("expect error: %v, got error: %v", test.expectErr, (err != nil))
|
t.Fatalf("expect error: %v, got error: %v", test.expectErr, (err != nil))
|
||||||
}
|
}
|
||||||
@ -230,20 +459,50 @@ func TestBaselineProfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"debug by pod copy": {
|
"debug by pod copy": {
|
||||||
pod: &corev1.Pod{
|
pod: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "podcopy",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
{Name: "dbg", Image: "dbgimage"},
|
{Name: "dbg", Image: "dbgimage"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
containerName: "dbg",
|
containerName: "dbg",
|
||||||
target: &corev1.Pod{
|
target: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "podcopy",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -251,6 +510,7 @@ func TestBaselineProfile(t *testing.T) {
|
|||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
ShareProcessNamespace: pointer.Bool(true),
|
ShareProcessNamespace: pointer.Bool(true),
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{Name: "app", Image: "appimage"},
|
||||||
{
|
{
|
||||||
@ -288,7 +548,8 @@ func TestBaselineProfile(t *testing.T) {
|
|||||||
|
|
||||||
for name, test := range tests {
|
for name, test := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
err := (&baselineProfile{}).Apply(test.pod, test.containerName, test.target)
|
applier := &baselineProfile{KeepFlags{InitContainers: true}}
|
||||||
|
err := applier.Apply(test.pod, test.containerName, test.target)
|
||||||
if (err != nil) != test.expectErr {
|
if (err != nil) != test.expectErr {
|
||||||
t.Fatalf("expect error: %v, got error: %v", test.expectErr, (err != nil))
|
t.Fatalf("expect error: %v, got error: %v", test.expectErr, (err != nil))
|
||||||
}
|
}
|
||||||
@ -357,20 +618,50 @@ func TestRestrictedProfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"debug by pod copy": {
|
"debug by pod copy": {
|
||||||
pod: &corev1.Pod{
|
pod: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "podcopy",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
{Name: "dbg", Image: "dbgimage"},
|
{Name: "dbg", Image: "dbgimage"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
containerName: "dbg",
|
containerName: "dbg",
|
||||||
target: &corev1.Pod{
|
target: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "podcopy",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -378,6 +669,7 @@ func TestRestrictedProfile(t *testing.T) {
|
|||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
ShareProcessNamespace: pointer.Bool(true),
|
ShareProcessNamespace: pointer.Bool(true),
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{Name: "app", Image: "appimage"},
|
||||||
{
|
{
|
||||||
@ -441,7 +733,8 @@ func TestRestrictedProfile(t *testing.T) {
|
|||||||
|
|
||||||
for name, test := range tests {
|
for name, test := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
err := (&restrictedProfile{}).Apply(test.pod, test.containerName, test.target)
|
applier := &restrictedProfile{KeepFlags{InitContainers: true}}
|
||||||
|
err := applier.Apply(test.pod, test.containerName, test.target)
|
||||||
if (err != nil) != test.expectErr {
|
if (err != nil) != test.expectErr {
|
||||||
t.Fatalf("expect error: %v, got error: %v", test.expectErr, (err != nil))
|
t.Fatalf("expect error: %v, got error: %v", test.expectErr, (err != nil))
|
||||||
}
|
}
|
||||||
@ -506,20 +799,50 @@ func TestNetAdminProfile(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "debug by pod copy",
|
name: "debug by pod copy",
|
||||||
pod: &corev1.Pod{
|
pod: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "podcopy",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
{Name: "dbg", Image: "dbgimage"},
|
{Name: "dbg", Image: "dbgimage"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
containerName: "dbg",
|
containerName: "dbg",
|
||||||
target: &corev1.Pod{
|
target: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "podcopy",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -527,6 +850,7 @@ func TestNetAdminProfile(t *testing.T) {
|
|||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
ShareProcessNamespace: pointer.Bool(true),
|
ShareProcessNamespace: pointer.Bool(true),
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{Name: "app", Image: "appimage"},
|
||||||
{
|
{
|
||||||
@ -548,7 +872,13 @@ func TestNetAdminProfile(t *testing.T) {
|
|||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "dbg",
|
Name: "dbg",
|
||||||
Image: "dbgimage",
|
Image: "dbgimage",
|
||||||
@ -566,7 +896,13 @@ func TestNetAdminProfile(t *testing.T) {
|
|||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -665,7 +1001,8 @@ func TestNetAdminProfile(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
err := (&netadminProfile{}).Apply(test.pod, test.containerName, test.target)
|
applier := &netadminProfile{KeepFlags{InitContainers: true}}
|
||||||
|
err := applier.Apply(test.pod, test.containerName, test.target)
|
||||||
if (err == nil) != (test.expectErr == nil) || (err != nil && test.expectErr != nil && err.Error() != test.expectErr.Error()) {
|
if (err == nil) != (test.expectErr == nil) || (err != nil && test.expectErr != nil && err.Error() != test.expectErr.Error()) {
|
||||||
t.Fatalf("expect error: %v, got error: %v", test.expectErr, err)
|
t.Fatalf("expect error: %v, got error: %v", test.expectErr, err)
|
||||||
}
|
}
|
||||||
@ -728,26 +1065,57 @@ func TestSysAdminProfile(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "debug by pod copy",
|
name: "debug by pod copy",
|
||||||
pod: &corev1.Pod{
|
pod: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "podcopy",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
{Name: "dbg", Image: "dbgimage"},
|
{Name: "dbg", Image: "dbgimage"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
containerName: "dbg",
|
containerName: "dbg",
|
||||||
target: &corev1.Pod{
|
target: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "podcopy",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "podcopy",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"test": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectPod: &corev1.Pod{
|
expectPod: &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
InitContainers: []corev1.Container{{Name: "init-container"}},
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{Name: "app", Image: "appimage"},
|
||||||
{
|
{
|
||||||
@ -768,7 +1136,13 @@ func TestSysAdminProfile(t *testing.T) {
|
|||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "dbg",
|
Name: "dbg",
|
||||||
Image: "dbgimage",
|
Image: "dbgimage",
|
||||||
@ -786,7 +1160,13 @@ func TestSysAdminProfile(t *testing.T) {
|
|||||||
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{Name: "app", Image: "appimage"},
|
{
|
||||||
|
Name: "app",
|
||||||
|
Image: "appimage",
|
||||||
|
LivenessProbe: &corev1.Probe{},
|
||||||
|
ReadinessProbe: &corev1.Probe{},
|
||||||
|
StartupProbe: &corev1.Probe{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -899,7 +1279,8 @@ func TestSysAdminProfile(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
err := (&sysadminProfile{}).Apply(test.pod, test.containerName, test.target)
|
applier := &sysadminProfile{KeepFlags{InitContainers: true}}
|
||||||
|
err := applier.Apply(test.pod, test.containerName, test.target)
|
||||||
if (err == nil) != (test.expectErr == nil) || (err != nil && test.expectErr != nil && err.Error() != test.expectErr.Error()) {
|
if (err == nil) != (test.expectErr == nil) || (err != nil && test.expectErr != nil && err.Error() != test.expectErr.Error()) {
|
||||||
t.Fatalf("expect error: %v, got error: %v", test.expectErr, err)
|
t.Fatalf("expect error: %v, got error: %v", test.expectErr, err)
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@ run_kubectl_debug_pod_tests() {
|
|||||||
kube::log::status "Testing kubectl debug (pod tests)"
|
kube::log::status "Testing kubectl debug (pod tests)"
|
||||||
|
|
||||||
### Pod Troubleshooting by ephemeral containers
|
### Pod Troubleshooting by ephemeral containers
|
||||||
|
|
||||||
# Pre-Condition: Pod "nginx" is created
|
# Pre-Condition: Pod "nginx" is created
|
||||||
kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
|
kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
|
||||||
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
|
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
|
||||||
@ -38,7 +37,6 @@ run_kubectl_debug_pod_tests() {
|
|||||||
kubectl delete pod target "${kube_flags[@]:?}"
|
kubectl delete pod target "${kube_flags[@]:?}"
|
||||||
|
|
||||||
### Pod Troubleshooting by Copy
|
### Pod Troubleshooting by Copy
|
||||||
|
|
||||||
# Pre-Condition: Pod "nginx" is created
|
# Pre-Condition: Pod "nginx" is created
|
||||||
kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
|
kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
|
||||||
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
|
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
|
||||||
@ -51,6 +49,26 @@ run_kubectl_debug_pod_tests() {
|
|||||||
# Clean up
|
# Clean up
|
||||||
kubectl delete pod target target-copy "${kube_flags[@]:?}"
|
kubectl delete pod target target-copy "${kube_flags[@]:?}"
|
||||||
|
|
||||||
|
# Pre-Condition: Pod "nginx" with labels, annotations, probes and initContainers is created
|
||||||
|
kubectl create -f hack/testdata/pod-with-metadata-and-probes.yaml
|
||||||
|
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
|
||||||
|
# Command: create a copy of target with a new debug container with --keep-* flags
|
||||||
|
# --keep-* flags intentionally don't work with legacyProfile(Only labels are removed)
|
||||||
|
kubectl debug target -it --copy-to=target-copy --image=busybox --container=debug-container --keep-labels=true --keep-annotations=true --keep-liveness=true --keep-readiness=true --keep-startup=true --keep-init-containers=false --attach=false "${kube_flags[@]:?}"
|
||||||
|
# Post-Conditions
|
||||||
|
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{.metadata.labels}}' '<no value>'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{.metadata.annotations}}' 'map\[test:test\]'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.name}}:{{end}}' 'target:debug-container:'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.image}}:{{end}}' "${IMAGE_NGINX:?}:busybox:"
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "livenessProbe")}}:{{end}}{{end}}' ':'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "readinessProbe")}}:{{end}}{{end}}' ':'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "startupProbe")}}:{{end}}{{end}}' ':'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.initContainers}}{{.name}}:{{end}}' 'init:'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.initContainers}}{{.image}}:{{end}}' "busybox:"
|
||||||
|
# Clean up
|
||||||
|
kubectl delete pod target target-copy "${kube_flags[@]:?}"
|
||||||
|
|
||||||
# Pre-Condition: Pod "nginx" is created
|
# Pre-Condition: Pod "nginx" is created
|
||||||
kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
|
kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
|
||||||
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
|
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
|
||||||
@ -133,20 +151,44 @@ run_kubectl_debug_general_tests() {
|
|||||||
kube::log::status "Testing kubectl debug profile general"
|
kube::log::status "Testing kubectl debug profile general"
|
||||||
|
|
||||||
### Debug by pod copy
|
### Debug by pod copy
|
||||||
### probes are removed, sets SYS_PTRACE in debugging container, sets shareProcessNamespace
|
# Pre-Condition: Pod "nginx" with labels, annotations, probes and initContainers is created
|
||||||
|
kubectl create -f hack/testdata/pod-with-metadata-and-probes.yaml
|
||||||
# Pre-Condition: Pod "nginx" is created
|
|
||||||
kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
|
|
||||||
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
|
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
|
||||||
# Command: create a copy of target with a new debug container
|
# Command: create a copy of target with a new debug container
|
||||||
|
# labels, annotations, probes are removed and initContainers are kept, sets SYS_PTRACE in debugging container, sets shareProcessNamespace
|
||||||
kubectl debug --profile general target -it --copy-to=target-copy --image=busybox --container=debug-container --attach=false "${kube_flags[@]:?}"
|
kubectl debug --profile general target -it --copy-to=target-copy --image=busybox --container=debug-container --attach=false "${kube_flags[@]:?}"
|
||||||
# Post-Conditions
|
# Post-Conditions
|
||||||
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
|
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{.metadata.labels}}' '<no value>'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{.metadata.annotations}}' '<no value>'
|
||||||
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.name}}:{{end}}' 'target:debug-container:'
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.name}}:{{end}}' 'target:debug-container:'
|
||||||
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.image}}:{{end}}' "${IMAGE_NGINX:?}:busybox:"
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.image}}:{{end}}' "${IMAGE_NGINX:?}:busybox:"
|
||||||
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "livenessProbe")}}:{{end}}{{end}}' ''
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "livenessProbe")}}:{{end}}{{end}}' ''
|
||||||
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "readinessProbe")}}:{{end}}{{end}}' ''
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "readinessProbe")}}:{{end}}{{end}}' ''
|
||||||
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "startupProbe")}}:{{end}}{{end}}' ''
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "startupProbe")}}:{{end}}{{end}}' ''
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.initContainers}}{{.name}}:{{end}}' 'init:'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.initContainers}}{{.image}}:{{end}}' "busybox:"
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{(index (index .spec.containers 1).securityContext.capabilities.add 0)}}' 'SYS_PTRACE'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{.spec.shareProcessNamespace}}' 'true'
|
||||||
|
# Clean up
|
||||||
|
kubectl delete pod target target-copy "${kube_flags[@]:?}"
|
||||||
|
|
||||||
|
# Pre-Condition: Pod "nginx" with labels, annotations, probes and initContainers is created
|
||||||
|
kubectl create -f hack/testdata/pod-with-metadata-and-probes.yaml
|
||||||
|
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
|
||||||
|
# Command: create a copy of target with a new debug container with --keep-* flags
|
||||||
|
# labels, annotations, probes are kept and initContainers are removed, sets SYS_PTRACE in debugging container, sets shareProcessNamespace
|
||||||
|
kubectl debug --profile general target -it --copy-to=target-copy --image=busybox --container=debug-container --keep-labels=true --keep-annotations=true --keep-liveness=true --keep-readiness=true --keep-startup=true --keep-init-containers=false --attach=false "${kube_flags[@]:?}"
|
||||||
|
# Post-Conditions
|
||||||
|
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{.metadata.labels}}' 'map\[run:target\]'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{.metadata.annotations}}' 'map\[test:test\]'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.name}}:{{end}}' 'target:debug-container:'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.image}}:{{end}}' "${IMAGE_NGINX:?}:busybox:"
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "livenessProbe")}}:{{end}}{{end}}' ':'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "readinessProbe")}}:{{end}}{{end}}' ':'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "startupProbe")}}:{{end}}{{end}}' ':'
|
||||||
|
kube::test::get_object_assert pod/target-copy '{{.spec.initContainers}}' '<no value>'
|
||||||
kube::test::get_object_assert pod/target-copy '{{(index (index .spec.containers 1).securityContext.capabilities.add 0)}}' 'SYS_PTRACE'
|
kube::test::get_object_assert pod/target-copy '{{(index (index .spec.containers 1).securityContext.capabilities.add 0)}}' 'SYS_PTRACE'
|
||||||
kube::test::get_object_assert pod/target-copy '{{.spec.shareProcessNamespace}}' 'true'
|
kube::test::get_object_assert pod/target-copy '{{.spec.shareProcessNamespace}}' 'true'
|
||||||
# Clean up
|
# Clean up
|
||||||
|
Loading…
Reference in New Issue
Block a user