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 panic with Job resource diffing against an unreachable cluster #3024

Merged
merged 4 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Unreleased

- Update to pulumi-java v0.12.0 #3025 (https://github.com/pulumi/pulumi-kubernetes/pull/3025)
- Fixed a panic that occurs when diffing Job resources containing `replaceUnready` annotations and an unreachable cluster connection. (https://github.com/pulumi/pulumi-kubernetes/pull/3024)

## 4.12.0 (May 21, 2024)

Expand Down
9 changes: 7 additions & 2 deletions provider/pkg/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1743,8 +1743,12 @@ func (k *kubeProvider) Diff(ctx context.Context, req *pulumirpc.DiffRequest) (*p
}

if metadata.ReplaceUnready(newInputs) {
switch newInputs.GetKind() {
case "Job":
switch {
case k.clusterUnreachable:
// Check if the cluster is unreachable. If it is, we can't check the status of the resource otherwise
// a panic occurs due to the client being nil.
_ = k.host.Log(ctx, diag.Warning, urn, "Cluster is unreachable, skipping replaceUnready check")
case newInputs.GetKind() == "Job":
// Fetch current Job status and check point-in-time readiness. Errors are ignored.
if live, err := k.readLiveObject(oldLive); err == nil {
jobChecker := checkjob.NewJobChecker()
Expand Down Expand Up @@ -2677,6 +2681,7 @@ func (k *kubeProvider) gvkFromURN(urn resource.URN) (schema.GroupVersionKind, er

func (k *kubeProvider) readLiveObject(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
contract.Assertf(obj.GetName() != "", "expected object name to be nonempty: %v", obj)
contract.Assertf(k.clientSet != nil, "expected Kubernetes client-set to be non-nil")
rc, err := k.clientSet.ResourceClientForObject(obj)
if err != nil {
return nil, err
Expand Down
32 changes: 32 additions & 0 deletions tests/sdk/java/testdata/job-unreachable/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: job-unreachable
runtime: yaml
resources:
provider:
type: pulumi:providers:kubernetes
job:
type: kubernetes:batch/v1:Job
properties:
metadata:
name: test-job-unreachable
annotations:
pulumi.com/replaceUnready: "true"
spec:
template:
metadata:
name: test-job-unreachable
spec:
containers:
- name: test-job-unreachable-container
image: busybox
# This command will cause the container to exit with a non-zero status code, and fail the job.
command:
- sh
- -c
- exit 1
restartPolicy: Never
options:
provider: ${provider}
customTimeouts:
create: 15s
update: 15s
delete: 15s
34 changes: 34 additions & 0 deletions tests/sdk/java/testdata/job-unreachable/step2/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: job-unreachable
runtime: yaml
resources:
provider:
type: pulumi:providers:kubernetes
properties:
kubeconfig: "fake-kubeconfig-data"
job:
type: kubernetes:batch/v1:Job
properties:
metadata:
name: test-job-unreachable
annotations:
pulumi.com/replaceUnready: "true"
spec:
template:
metadata:
name: test-job-unreachable
spec:
containers:
- name: test-job-unreachable-container
image: busybox
# This command will cause the container to exit with a non-zero status code, and fail the job.
command:
- sh
- -c
- exit 1
restartPolicy: Never
options:
provider: ${provider}
customTimeouts:
create: 15s
update: 15s
delete: 15s
21 changes: 21 additions & 0 deletions tests/sdk/java/yamlv2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"

"github.com/pulumi/providertest/pulumitest"
"github.com/stretchr/testify/assert"
)

// TestYamlV2 deploys a complex stack using yaml/v2 package.
Expand All @@ -21,3 +22,23 @@ func TestYamlV2(t *testing.T) {
test.Preview()
test.Up()
}

// TestJobUnreachable ensures that a panic does not occur when diffing Job resources against an unreachable API server.
// https://github.com/pulumi/pulumi-kubernetes/issues/3022
func TestJobUnreachable(t *testing.T) {
test := pulumitest.NewPulumiTest(t, "testdata/job-unreachable")
t.Logf("into %s", test.Source())
t.Cleanup(func() {
test.Destroy()
})
test.Preview()

// Create the job, but expect it to fail as the job is meant to fail.
_, err := test.CurrentStack().Up(test.Context())
assert.ErrorContains(t, err, `but the Kubernetes API server reported that it failed to fully initialize or become live`)

// Re-run the Pulumi program with a malformed kubeconfig to simulate an unreachable API server.
// This should not panic annd preview should succeed.
test.UpdateSource("testdata/job-unreachable/step2")
test.Preview()
}
Loading