diff --git a/pkg/cli/commands/rpkg/del/command_test.go b/pkg/cli/commands/rpkg/del/command_test.go new file mode 100644 index 00000000..e2680846 --- /dev/null +++ b/pkg/cli/commands/rpkg/del/command_test.go @@ -0,0 +1,113 @@ +// Copyright 2022 The kpt and Nephio Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package del + +import ( + "context" + "io" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + porchapi "github.com/nephio-project/porch/api/porch/v1alpha1" + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/genericclioptions" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +func createScheme() (*runtime.Scheme, error) { + scheme := runtime.NewScheme() + + for _, api := range (runtime.SchemeBuilder{ + porchapi.AddToScheme, + }) { + if err := api(scheme); err != nil { + return nil, err + } + } + return scheme, nil +} + +func TestCmd(t *testing.T) { + pkgRevName := "test-fjdos9u2nfe2f32" + var scheme, err = createScheme() + if err != nil { + t.Fatalf("error creating scheme: %v", err) + } + testCases := map[string]struct { + output string + wantErr bool + ns string + }{ + "Package not found in ns": { + output: pkgRevName + " failed (packagerevisions.porch.kpt.dev \"" + pkgRevName + "\" not found)\n", + ns: "doesnotexist", + wantErr: true, + }, + "delete package": { + output: pkgRevName + " deleted\n", + ns: "ns", + }, + } + + for tn := range testCases { + tc := testCases[tn] + t.Run(tn, func(t *testing.T) { + c := fake.NewClientBuilder(). + WithScheme(scheme). + WithObjects(&porchapi.PackageRevision{ + TypeMeta: metav1.TypeMeta{ + Kind: "PackageRevision", + APIVersion: porchapi.SchemeGroupVersion.Identifier(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "ns", + Name: pkgRevName, + }}).Build() + + cmd := &cobra.Command{} + o := os.Stdout + e := os.Stderr + read, write, _ := os.Pipe() + os.Stdout = write + os.Stderr = write + + r := &runner{ + ctx: context.Background(), + cfg: &genericclioptions.ConfigFlags{ + Namespace: &tc.ns, + }, + client: c, + Command: cmd, + } + go func() { + defer write.Close() + err := r.runE(cmd, []string{pkgRevName}) + if err != nil && !tc.wantErr { + t.Errorf("unexpected error: %v", err) + } + }() + out, _ := io.ReadAll(read) + os.Stdout = o + os.Stderr = e + + if diff := cmp.Diff(string(tc.output), string(out)); diff != "" { + t.Errorf("Unexpected result (-want, +got): %s", diff) + } + }) + } +} diff --git a/pkg/cli/commands/rpkg/propose/command_test.go b/pkg/cli/commands/rpkg/propose/command_test.go new file mode 100644 index 00000000..cab886c0 --- /dev/null +++ b/pkg/cli/commands/rpkg/propose/command_test.go @@ -0,0 +1,122 @@ +// Copyright 2022 The kpt and Nephio Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package propose + +import ( + "context" + "io" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + porchapi "github.com/nephio-project/porch/api/porch/v1alpha1" + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/genericclioptions" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +func createScheme() (*runtime.Scheme, error) { + scheme := runtime.NewScheme() + + for _, api := range (runtime.SchemeBuilder{ + porchapi.AddToScheme, + }) { + if err := api(scheme); err != nil { + return nil, err + } + } + return scheme, nil +} + +func TestCmd(t *testing.T) { + pkgRevName := "test-fjdos9u2nfe2f32" + ns := "ns" + var scheme, err = createScheme() + if err != nil { + t.Fatalf("error creating scheme: %v", err) + } + testCases := map[string]struct { + lc porchapi.PackageRevisionLifecycle + output string + wantErr bool + }{ + "Package already proposed": { + output: pkgRevName + " is already proposed\n", + lc: porchapi.PackageRevisionLifecycleProposed, + }, + "Propose package": { + output: pkgRevName + " proposed\n", + lc: porchapi.PackageRevisionLifecycleDraft, + }, + "Cannot propose package": { + output: "cannot propose Published package\n", + lc: porchapi.PackageRevisionLifecyclePublished, + wantErr: true, + }, + } + + for tn := range testCases { + tc := testCases[tn] + t.Run(tn, func(t *testing.T) { + c := fake.NewClientBuilder(). + WithScheme(scheme). + WithObjects(&porchapi.PackageRevision{ + TypeMeta: metav1.TypeMeta{ + Kind: "PackageRevision", + APIVersion: porchapi.SchemeGroupVersion.Identifier(), + }, + Spec: porchapi.PackageRevisionSpec{ + Lifecycle: tc.lc, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns, + Name: pkgRevName, + }, + }).Build() + + cmd := &cobra.Command{} + o := os.Stdout + e := os.Stderr + read, write, _ := os.Pipe() + os.Stdout = write + os.Stderr = write + + r := &runner{ + ctx: context.Background(), + cfg: &genericclioptions.ConfigFlags{ + Namespace: &ns, + }, + client: c, + Command: cmd, + } + go func() { + defer write.Close() + err := r.runE(cmd, []string{pkgRevName}) + if err != nil && !tc.wantErr { + t.Errorf("unexpected error: %v", err) + } + }() + out, _ := io.ReadAll(read) + os.Stdout = o + os.Stderr = e + + if diff := cmp.Diff(string(tc.output), string(out)); diff != "" { + t.Errorf("Unexpected result (-want, +got): %s", diff) + } + }) + } +} diff --git a/pkg/cli/commands/rpkg/proposedelete/command_test.go b/pkg/cli/commands/rpkg/proposedelete/command_test.go new file mode 100644 index 00000000..5cfce9e6 --- /dev/null +++ b/pkg/cli/commands/rpkg/proposedelete/command_test.go @@ -0,0 +1,127 @@ +// Copyright 2022 The kpt and Nephio Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proposedelete + +import ( + "context" + "io" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + porchapi "github.com/nephio-project/porch/api/porch/v1alpha1" + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/genericclioptions" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +func createScheme() (*runtime.Scheme, error) { + scheme := runtime.NewScheme() + + for _, api := range (runtime.SchemeBuilder{ + porchapi.AddToScheme, + }) { + if err := api(scheme); err != nil { + return nil, err + } + } + return scheme, nil +} + +func TestCmd(t *testing.T) { + pkgRevName := "test-fjdos9u2nfe2f32" + var scheme, err = createScheme() + if err != nil { + t.Fatalf("error creating scheme: %v", err) + } + testCases := map[string]struct { + lc porchapi.PackageRevisionLifecycle + output string + wantErr bool + ns string + }{ + "Package not found in ns": { + ns: "doesnotexist", + wantErr: true, + }, + "Package not published": { + output: "can only propose published packages for deletion; package " + pkgRevName + " is not published\n", + ns: "ns", + wantErr: true, + }, + "Already propose for deletion": { + lc: porchapi.PackageRevisionLifecycleDeletionProposed, + output: pkgRevName + " is already proposed for deletion\n", + ns: "ns", + }, + "Propose delete package": { + lc: porchapi.PackageRevisionLifecyclePublished, + output: pkgRevName + " proposed for deletion\n", + ns: "ns", + }, + } + + for tn := range testCases { + tc := testCases[tn] + t.Run(tn, func(t *testing.T) { + c := fake.NewClientBuilder(). + WithScheme(scheme). + WithObjects(&porchapi.PackageRevision{ + TypeMeta: metav1.TypeMeta{ + Kind: "PackageRevision", + APIVersion: porchapi.SchemeGroupVersion.Identifier(), + }, + Spec: porchapi.PackageRevisionSpec{ + Lifecycle: tc.lc, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "ns", + Name: pkgRevName, + }}).Build() + + cmd := &cobra.Command{} + o := os.Stdout + e := os.Stderr + read, write, _ := os.Pipe() + os.Stdout = write + os.Stderr = write + + r := &runner{ + ctx: context.Background(), + cfg: &genericclioptions.ConfigFlags{ + Namespace: &tc.ns, + }, + client: c, + Command: cmd, + } + go func() { + defer write.Close() + err := r.runE(cmd, []string{pkgRevName}) + if err != nil && !tc.wantErr { + t.Errorf("unexpected error: %v", err) + } + }() + out, _ := io.ReadAll(read) + os.Stdout = o + os.Stderr = e + + if diff := cmp.Diff(string(tc.output), string(out)); diff != "" { + t.Errorf("Unexpected result (-want, +got): %s", diff) + } + }) + } +} diff --git a/pkg/cli/commands/rpkg/push/command_test.go b/pkg/cli/commands/rpkg/push/command_test.go new file mode 100644 index 00000000..bc6e3283 --- /dev/null +++ b/pkg/cli/commands/rpkg/push/command_test.go @@ -0,0 +1,110 @@ +// Copyright 2022 The kpt and Nephio Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package push + +import ( + "bytes" + "io" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + porchapi "github.com/nephio-project/porch/api/porch/v1alpha1" + "github.com/nephio-project/porch/pkg/kpt/printer" + fakeprint "github.com/nephio-project/porch/pkg/kpt/printer/fake" + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/cli-runtime/pkg/genericclioptions" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +func TestCmd(t *testing.T) { + pkgRevName := "test-fjdos9u2nfe2f32" + ns := "ns" + pkgDir := "testdata/test-fjdos9u2nfe2f32" + + scheme, err := createScheme() + if err != nil { + t.Fatalf("error creating scheme: %v", err) + } + + testCases := map[string]struct { + output string + args []string + wantErr bool + }{ + "Push package": { + output: pkgRevName + " pushed\n", + args: []string{pkgRevName, pkgDir}, + }, + "Args not provided": { + wantErr: true, + }, + "Pkgdir not provided": { + args: []string{pkgRevName}, + wantErr: true, + }, + ".KptRevisionMetadata missing": { + args: []string{pkgRevName, "dummy"}, + wantErr: true, + }, + } + + for tn := range testCases { + tc := testCases[tn] + t.Run(tn, func(t *testing.T) { + c := fake.NewClientBuilder(). + WithScheme(scheme). + WithObjects(&porchapi.PackageRevisionResources{ + ObjectMeta: metav1.ObjectMeta{ + Name: pkgRevName, + Namespace: ns, + }, + }). + Build() + output := &bytes.Buffer{} + o := os.Stdout + e := os.Stderr + read, write, _ := os.Pipe() + os.Stdout = write + os.Stderr = write + ctx := fakeprint.CtxWithPrinter(output, output) + r := &runner{ + ctx: ctx, + cfg: &genericclioptions.ConfigFlags{ + Namespace: &ns, + }, + client: c, + printer: printer.FromContextOrDie(ctx), + } + cmd := &cobra.Command{} + + go func() { + defer write.Close() + err := r.runE(cmd, tc.args) + if err != nil && !tc.wantErr { + t.Errorf("unexpected error: %v", err) + } + }() + io.Copy(output, read) + os.Stdout = o + os.Stderr = e + + if diff := cmp.Diff(string(tc.output), output.String()); diff != "" { + t.Errorf("Unexpected result (-want, +got): %s", diff) + } + }) + } +} diff --git a/pkg/cli/commands/rpkg/push/testdata/test-fjdos9u2nfe2f32/.KptRevisionMetadata b/pkg/cli/commands/rpkg/push/testdata/test-fjdos9u2nfe2f32/.KptRevisionMetadata new file mode 100644 index 00000000..b10dde85 --- /dev/null +++ b/pkg/cli/commands/rpkg/push/testdata/test-fjdos9u2nfe2f32/.KptRevisionMetadata @@ -0,0 +1,12 @@ +apiVersion: porch.kpt.dev/v1alpha1 +kind: KptRevisionMetadata +metadata: + name: test-fjdos9u2nfe2f32 + namespace: ns + creationTimestamp: null + resourceVersion: "999" + annotations: + config.kubernetes.io/index: '0' + internal.config.kubernetes.io/index: '0' + internal.config.kubernetes.io/path: '.KptRevisionMetadata' + config.kubernetes.io/path: '.KptRevisionMetadata' \ No newline at end of file diff --git a/pkg/cli/commands/rpkg/push/testdata/test-fjdos9u2nfe2f32/deployment.yaml b/pkg/cli/commands/rpkg/push/testdata/test-fjdos9u2nfe2f32/deployment.yaml new file mode 100644 index 00000000..98d48d7b --- /dev/null +++ b/pkg/cli/commands/rpkg/push/testdata/test-fjdos9u2nfe2f32/deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-fjdos9u2nfe2f32 + annotations: + config.kubernetes.io/index: '0' + internal.config.kubernetes.io/index: '0' + internal.config.kubernetes.io/path: 'deployment.yaml' + config.kubernetes.io/path: 'deployment.yaml' +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: test-fjdos9u2nfe2f32 + template: + metadata: + labels: + app.kubernetes.io/name: test-fjdos9u2nfe2f32 + spec: + containers: + - name: nginx + image: nginx:latest