Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sync): log a warning for empty pods #9599

Merged
merged 3 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions pkg/skaffold/sync/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,10 @@ func Perform(ctx context.Context, image string, files syncMap, cmdFn func(contex
return nil
}

if len(namespaces) == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any way to add a test for this? not sure if that's possible with the current unit test setup

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

were you able to reproduce the issue and confirm this fixes it? In the bug they filed, I didn't see anything in the logs to indicate what the issue was

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's just an assumption, because according to the log if something went wrong, it returns error, but it doesn't return any specific error if there is no namespaces OR nor running pod was found

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these logs should be merged regardless of the issue, because in these cases(empty namespaces or no running pods) there is no way to know what went wrong

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I would delete this line as it'll never be hit. Specifically here: https://github.com/GoogleContainerTools/skaffold/blob/main/pkg/skaffold/deploy/util/namespaces.go#L35C4-L35C26 if the namespace is empty, it gets the kube context's namespace. If nothing was set, the default namespace is used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return fmt.Errorf("no namespaces provided for syncing")
}

errs, ctx := errgroup.WithContext(ctx)

client, err := kubernetesclient.Client(kubeContext)
Expand All @@ -340,10 +344,16 @@ func Perform(ctx context.Context, image string, files syncMap, cmdFn func(contex
pods, err := client.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{
FieldSelector: fmt.Sprintf("status.phase=%s", v1.PodRunning),
})

if err != nil {
return fmt.Errorf("getting pods for namespace %q: %w", ns, err)
}

if len(pods.Items) == 0 {
log.Entry(ctx).Warnf("no running pods found in namespace %q", ns)
continue
}

for _, p := range pods.Items {
for _, c := range p.Spec.Containers {
if c.Image != image {
Expand Down
32 changes: 27 additions & 5 deletions pkg/skaffold/sync/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@ func fakeCmd(ctx context.Context, _ v1.Pod, _ v1.Container, files syncMap) *exec
return exec.CommandContext(ctx, "copy", args...)
}

var pod = &v1.Pod{
var runningPod = &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "podname",
},
Expand Down Expand Up @@ -936,15 +936,15 @@ func TestPerform(t *testing.T) {
description: "no error",
image: "gcr.io/k8s-skaffold:123",
files: syncMap{"test.go": {"/test.go"}},
pod: pod,
pod: runningPod,
cmdFn: fakeCmd,
expected: []string{"copy test.go /test.go"},
},
{
description: "cmd error",
image: "gcr.io/k8s-skaffold:123",
files: syncMap{"test.go": {"/test.go"}},
pod: pod,
pod: runningPod,
cmdFn: fakeCmd,
cmdErr: fmt.Errorf(""),
shouldErr: true,
Expand All @@ -953,16 +953,24 @@ func TestPerform(t *testing.T) {
description: "client error",
image: "gcr.io/k8s-skaffold:123",
files: syncMap{"test.go": {"/test.go"}},
pod: pod,
pod: runningPod,
cmdFn: fakeCmd,
clientErr: fmt.Errorf(""),
shouldErr: true,
},
{
description: "pod not running",
image: "gcr.io/k8s-skaffold:123",
files: syncMap{"test.go": {"/test.go"}},
pod: nil,
cmdFn: fakeCmd,
shouldErr: true,
},
{
description: "no copy",
image: "gcr.io/different-pod:123",
files: syncMap{"test.go": {"/test.go"}},
pod: pod,
pod: runningPod,
cmdFn: fakeCmd,
shouldErr: true,
},
Expand All @@ -973,6 +981,10 @@ func TestPerform(t *testing.T) {

t.Override(&util.DefaultExecCommand, cmdRecord)
t.Override(&client.Client, func(string) (kubernetes.Interface, error) {
if test.pod == nil {
return fake.NewSimpleClientset(), nil
}

return fake.NewSimpleClientset(test.pod), test.clientErr
})

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are no namespaces being given below in Perform the arg is `[]string{""} - why does the first test case still work "no error"? Is there a default namespace being used?

instead of adding a new test (i.e. TestPerform_WithoutNamespaces) could you just add another test case here? First add a new value to the test struct "namespaces", add to existing tests and then pass that along when calling Perform. And in that test case you'd have an empty namespace.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because it's []string{""} slice of 1 item and the item is an empty string, this is why the len returns a non-zero value and it works.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about adding one more test case to the old test, but it'll complicate the test, so decided to create a separate test

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment it turns out we don't need to check for empty namespaces and can remove the separate test. Appreciate the explanation though.

Expand All @@ -983,6 +995,16 @@ func TestPerform(t *testing.T) {
}
}

func TestPerform_WithoutNamespaces(t *testing.T) {
err := Perform(context.Background(), "", syncMap{"test.go": {"/test.go"}}, nil, []string{}, "")

if err != nil {
testutil.CheckErrorAndDeepEqual(t, true, err, "no namespaces provided for syncing", err.Error())
} else {
testutil.CheckError(t, true, err)
}
}

func TestSyncMap(t *testing.T) {
tests := []struct {
description string
Expand Down