From b71a36dc1c8cc33e4218b5b69381a31983924c93 Mon Sep 17 00:00:00 2001 From: neha_gupta Date: Mon, 7 Nov 2022 21:42:39 +0530 Subject: [PATCH] Use Kubernetes Client instead of Controller APIs from CLI (#2605) Use the Kubernetes and Fission Client from CLI instead of Controller API. This removes port-forwarding for the controller across Fission CLI mostly. * Use configurable client in CLI * Move resource namespace under cmd client * use server to get fission version * get archive with URL Signed-off-by: Sanket Sudake Co-authored-by: Sanket Sudake --- cmd/fission-cli/app/app.go | 26 +- pkg/controller/api.go | 2 +- pkg/controller/api_test.go | 135 +++++---- pkg/controller/client/v1/canaryconfig.go | 3 +- pkg/controller/client/v1/fake/fake_package.go | 3 +- .../client/v1/fake/fake_timetrigger.go | 3 +- pkg/controller/client/v1/httptrigger.go | 3 +- .../client/v1/kuberneteswatchtrigger.go | 3 +- pkg/controller/client/v1/mqtrigger.go | 3 +- pkg/controller/client/v1/package.go | 3 +- pkg/controller/client/v1/timetrigger.go | 3 +- pkg/controller/client/v1/v1.go | 3 +- pkg/fission-cli/cmd/archive/command.go | 8 +- pkg/fission-cli/cmd/archive/delete.go | 3 +- pkg/fission-cli/cmd/archive/download.go | 3 +- pkg/fission-cli/cmd/archive/geturl.go | 5 +- pkg/fission-cli/cmd/archive/list.go | 5 +- pkg/fission-cli/cmd/archive/upload.go | 3 +- pkg/fission-cli/cmd/canaryconfig/create.go | 12 +- pkg/fission-cli/cmd/canaryconfig/delete.go | 10 +- pkg/fission-cli/cmd/canaryconfig/get.go | 8 +- pkg/fission-cli/cmd/canaryconfig/list.go | 14 +- pkg/fission-cli/cmd/canaryconfig/update.go | 11 +- pkg/fission-cli/cmd/check/check.go | 9 +- pkg/fission-cli/cmd/client.go | 134 ++++++++ pkg/fission-cli/cmd/cmd.go | 40 ++- pkg/fission-cli/cmd/environment/create.go | 16 +- pkg/fission-cli/cmd/environment/delete.go | 24 +- pkg/fission-cli/cmd/environment/get.go | 10 +- pkg/fission-cli/cmd/environment/list.go | 13 +- pkg/fission-cli/cmd/environment/pods.go | 30 +- pkg/fission-cli/cmd/environment/update.go | 15 +- pkg/fission-cli/cmd/function/create.go | 35 +-- pkg/fission-cli/cmd/function/delete.go | 4 +- pkg/fission-cli/cmd/function/get.go | 13 +- pkg/fission-cli/cmd/function/getmeta.go | 8 +- pkg/fission-cli/cmd/function/list.go | 14 +- pkg/fission-cli/cmd/function/log.go | 10 +- pkg/fission-cli/cmd/function/pods.go | 25 +- pkg/fission-cli/cmd/function/run_container.go | 32 +- pkg/fission-cli/cmd/function/test.go | 29 +- pkg/fission-cli/cmd/function/update.go | 28 +- .../cmd/function/update_container.go | 20 +- pkg/fission-cli/cmd/httptrigger/create.go | 26 +- pkg/fission-cli/cmd/httptrigger/delete.go | 11 +- pkg/fission-cli/cmd/httptrigger/get.go | 9 +- pkg/fission-cli/cmd/httptrigger/list.go | 12 +- pkg/fission-cli/cmd/httptrigger/update.go | 17 +- pkg/fission-cli/cmd/kubewatch/create.go | 4 +- pkg/fission-cli/cmd/kubewatch/delete.go | 7 +- pkg/fission-cli/cmd/kubewatch/list.go | 14 +- pkg/fission-cli/cmd/mqtrigger/create.go | 6 +- pkg/fission-cli/cmd/mqtrigger/delete.go | 8 +- pkg/fission-cli/cmd/mqtrigger/list.go | 14 +- pkg/fission-cli/cmd/mqtrigger/update.go | 11 +- pkg/fission-cli/cmd/package/create.go | 10 +- pkg/fission-cli/cmd/package/delete.go | 36 +-- pkg/fission-cli/cmd/package/get.go | 16 +- pkg/fission-cli/cmd/package/info.go | 12 +- pkg/fission-cli/cmd/package/list.go | 19 +- pkg/fission-cli/cmd/package/package.go | 12 +- pkg/fission-cli/cmd/package/rebuild.go | 13 +- pkg/fission-cli/cmd/package/update.go | 33 +- pkg/fission-cli/cmd/package/util/util.go | 98 +++++- pkg/fission-cli/cmd/spec/apply.go | 208 +++++++------ pkg/fission-cli/cmd/spec/buildwatch.go | 11 +- pkg/fission-cli/cmd/spec/destroy.go | 69 ++--- pkg/fission-cli/cmd/spec/list.go | 77 ++--- pkg/fission-cli/cmd/spec/spec.go | 19 +- pkg/fission-cli/cmd/spec/validate.go | 22 +- pkg/fission-cli/cmd/support/dump.go | 9 +- pkg/fission-cli/cmd/support/resources/crd.go | 42 ++- .../cmd/support/resources/fissionversion.go | 12 +- pkg/fission-cli/cmd/timetrigger/create.go | 18 +- pkg/fission-cli/cmd/timetrigger/delete.go | 14 +- pkg/fission-cli/cmd/timetrigger/list.go | 13 +- pkg/fission-cli/cmd/timetrigger/test.go | 8 +- pkg/fission-cli/cmd/timetrigger/update.go | 14 +- pkg/fission-cli/cmd/token/create.go | 3 +- pkg/fission-cli/cmd/version/version.go | 2 +- pkg/fission-cli/util/portforward.go | 19 +- pkg/fission-cli/util/util.go | 286 ++++++++++-------- pkg/fission-cli/util/util_test.go | 14 +- pkg/healthcheck/healthcheck.go | 45 ++- pkg/storagesvc/client/client.go | 15 + pkg/utils/otel/log.go | 4 +- 86 files changed, 1115 insertions(+), 978 deletions(-) create mode 100644 pkg/fission-cli/cmd/client.go diff --git a/cmd/fission-cli/app/app.go b/cmd/fission-cli/app/app.go index 08da49f8..3bbbe9c9 100644 --- a/cmd/fission-cli/app/app.go +++ b/cmd/fission-cli/app/app.go @@ -14,10 +14,9 @@ limitations under the License. package app import ( + "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/fission/fission/pkg/controller/client" - "github.com/fission/fission/pkg/controller/client/rest" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" wrapper "github.com/fission/fission/pkg/fission-cli/cliwrapper/driver/cobra" "github.com/fission/fission/pkg/fission-cli/cliwrapper/driver/cobra/helptemplate" @@ -39,7 +38,6 @@ import ( "github.com/fission/fission/pkg/fission-cli/console" "github.com/fission/fission/pkg/fission-cli/flag" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" _ "github.com/fission/fission/pkg/mqtrigger/messageQueue/kafka" ) @@ -61,19 +59,17 @@ func App() *cobra.Command { PersistentPreRunE: wrapper.Wrapper( func(input cli.Input) error { console.Verbosity = input.Int(flagkey.Verbosity) - - if input.IsSet(flagkey.ClientOnly) || input.IsSet(flagkey.PreCheckOnly) { - // TODO: use fake rest client for offline spec generation - cmd.SetClientset(client.MakeFakeClientset(nil)) - } else { - serverUrl, err := util.GetServerURL(input) - if err != nil { - return err - } - restClient := rest.NewRESTClient(serverUrl) - cmd.SetClientset(client.MakeClientset(restClient)) + clientOptions := cmd.ClientOptions{ + KubeContext: input.String(flagkey.KubeContext), } - + // TODO: use fake rest client for offline spec generation + // if input.IsSet(flagkey.ClientOnly) || input.IsSet(flagkey.PreCheckOnly) { + // } + client, err := cmd.NewClient(clientOptions) + if err != nil { + return errors.Wrap(err, "failed to get fission client") + } + cmd.SetClientset(*client) return nil }, ), diff --git a/pkg/controller/api.go b/pkg/controller/api.go index 5d049f57..d99a2088 100644 --- a/pkg/controller/api.go +++ b/pkg/controller/api.go @@ -261,7 +261,7 @@ func (api *API) GetHandler() http.Handler { r.HandleFunc("/proxy/{dbType}", api.FunctionLogsApiPost).Methods("POST") r.HandleFunc("/proxy/storage/v1/archive", api.StorageServiceProxy) r.HandleFunc("/proxy/logs/{function}", api.FunctionPodLogs).Methods("POST") - r.HandleFunc("/proxy/workflows-apiserver/{path:.*}", api.WorkflowApiserverProxy) + r.HandleFunc("/proxy/workflows-apiserver/{path:.*}", api.WorkflowApiserverProxy) // Deprecated r.HandleFunc("/proxy/svcname", api.GetSvcName).Queries("application", "").Methods("GET") r.Handle("/v2/apidocs.json", openAPI()).Methods("GET") diff --git a/pkg/controller/api_test.go b/pkg/controller/api_test.go index 2aeefe20..e6d13b16 100644 --- a/pkg/controller/api_test.go +++ b/pkg/controller/api_test.go @@ -44,9 +44,9 @@ import ( ) var ( - g struct { - cmd.CommandActioner - } + // g struct { + // cmd.CommandActioner + // } testNS = metav1.NamespaceDefault ) @@ -105,41 +105,45 @@ func TestFunctionApi(t *testing.T) { }, }, } - _, err := g.Client().V1().Function().Get(&metav1.ObjectMeta{ + + restClient := rest.NewRESTClient("http://localhost:8888") + dClient := client.MakeClientset(restClient) + + _, err := dClient.V1().Function().Get(&metav1.ObjectMeta{ Name: testFunc.ObjectMeta.Name, Namespace: testNS, }) assertNotFoundFailure(err, "function") - m, err := g.Client().V1().Function().Create(testFunc) + m, err := dClient.V1().Function().Create(testFunc) panicIf(err) defer func() { - err := g.Client().V1().Function().Delete(m) + err := dClient.V1().Function().Delete(m) panicIf(err) }() - _, err = g.Client().V1().Function().Create(testFunc) + _, err = dClient.V1().Function().Create(testFunc) assertNameReuseFailure(err, "function") testFunc.ObjectMeta.ResourceVersion = m.ResourceVersion testFunc.Spec.Package.FunctionName = "yyy" - _, err = g.Client().V1().Function().Update(testFunc) + _, err = dClient.V1().Function().Update(testFunc) panicIf(err) testFunc.ObjectMeta.ResourceVersion = "" testFunc.ObjectMeta.Name = "bar" - m2, err := g.Client().V1().Function().Create(testFunc) + m2, err := dClient.V1().Function().Create(testFunc) panicIf(err) defer func() { - err := g.Client().V1().Function().Delete(m2) + err := dClient.V1().Function().Delete(m2) panicIf(err) }() - funcs, err := g.Client().V1().Function().List(testNS) + funcs, err := dClient.V1().Function().List(testNS) panicIf(err) assert(len(funcs) == 2, fmt.Sprintf("created two functions, but found %v", len(funcs))) - funcs_url := g.Client().ServerURL() + "/v2/functions" + funcs_url := dClient.ServerURL() + "/v2/functions" resp, err := http.Get(funcs_url) panicIf(err) defer resp.Body.Close() @@ -169,23 +173,27 @@ func TestHTTPTriggerApi(t *testing.T) { }, }, } - _, err := g.Client().V1().HTTPTrigger().Get(&metav1.ObjectMeta{ + + restClient := rest.NewRESTClient("http://localhost:8888") + dClient := client.MakeClientset(restClient) + + _, err := dClient.V1().HTTPTrigger().Get(&metav1.ObjectMeta{ Name: testTrigger.ObjectMeta.Name, Namespace: testNS, }) assertNotFoundFailure(err, "httptrigger") - m, err := g.Client().V1().HTTPTrigger().Create(testTrigger) + m, err := dClient.V1().HTTPTrigger().Create(testTrigger) panicIf(err) defer func() { - err := g.Client().V1().HTTPTrigger().Delete(m) + err := dClient.V1().HTTPTrigger().Delete(m) panicIf(err) }() - _, err = g.Client().V1().HTTPTrigger().Create(testTrigger) + _, err = dClient.V1().HTTPTrigger().Create(testTrigger) assertNameReuseFailure(err, "httptrigger") - tr, err := g.Client().V1().HTTPTrigger().Get(m) + tr, err := dClient.V1().HTTPTrigger().Get(m) panicIf(err) assert(len(testTrigger.Spec.Methods) == len(tr.Spec.Methods) && testTrigger.Spec.RelativeURL == tr.Spec.RelativeURL && @@ -194,23 +202,23 @@ func TestHTTPTriggerApi(t *testing.T) { testTrigger.ObjectMeta.ResourceVersion = m.ResourceVersion testTrigger.Spec.RelativeURL = "/hi" - _, err = g.Client().V1().HTTPTrigger().Update(testTrigger) + _, err = dClient.V1().HTTPTrigger().Update(testTrigger) panicIf(err) testTrigger.ObjectMeta.ResourceVersion = "" testTrigger.ObjectMeta.Name = "yyy" - _, err = g.Client().V1().HTTPTrigger().Create(testTrigger) + _, err = dClient.V1().HTTPTrigger().Create(testTrigger) assert(err != nil, "duplicate trigger should not be allowed") testTrigger.Spec.RelativeURL = "/hi2" - m2, err := g.Client().V1().HTTPTrigger().Create(testTrigger) + m2, err := dClient.V1().HTTPTrigger().Create(testTrigger) panicIf(err) defer func() { - err = g.Client().V1().HTTPTrigger().Delete(m2) + err = dClient.V1().HTTPTrigger().Delete(m2) panicIf(err) }() - ts, err := g.Client().V1().HTTPTrigger().List(testNS) + ts, err := dClient.V1().HTTPTrigger().List(testNS) panicIf(err) assert(len(ts) == 2, fmt.Sprintf("created two triggers, but found %v", len(ts))) } @@ -237,7 +245,9 @@ func createFissionFnForMultipleTrigger() { }, } - _, err := g.Client().V1().Function().Create(testFunc) + restClient := rest.NewRESTClient("http://localhost:8888") + dClient := client.MakeClientset(restClient) + _, err := dClient.V1().Function().Create(testFunc) panicIf(err) defer func() { panicIf(err) @@ -245,7 +255,7 @@ func createFissionFnForMultipleTrigger() { testFunc.Name = "foo2" - _, err = g.Client().V1().Function().Create(testFunc) + _, err = dClient.V1().Function().Create(testFunc) panicIf(err) defer func() { panicIf(err) @@ -272,9 +282,11 @@ func TestHTTPTriggerCreateMultipleTrigger(t *testing.T) { }, } - m, err := g.Client().V1().HTTPTrigger().Create(testTrigger) + restClient := rest.NewRESTClient("http://localhost:8888") + dClient := client.MakeClientset(restClient) + m, err := dClient.V1().HTTPTrigger().Create(testTrigger) panicIf(err) - defer panicIf(g.Client().V1().HTTPTrigger().Delete(m)) + defer panicIf(dClient.V1().HTTPTrigger().Delete(m)) prefix_2 := "url_another" testTrigger2 := &fv1.HTTPTrigger{ @@ -293,7 +305,7 @@ func TestHTTPTriggerCreateMultipleTrigger(t *testing.T) { }, } - m2, err := g.Client().V1().HTTPTrigger().Create(testTrigger2) + m2, err := dClient.V1().HTTPTrigger().Create(testTrigger2) if err != nil { t.Fatal() @@ -301,7 +313,7 @@ func TestHTTPTriggerCreateMultipleTrigger(t *testing.T) { defer func() { if m2 != nil { - err := g.Client().V1().HTTPTrigger().Delete(m2) + err := dClient.V1().HTTPTrigger().Delete(m2) if err != nil { logger.Error("Error deleting http trigger", zap.String("name", m2.Name), zap.Error(err)) } @@ -324,42 +336,46 @@ func TestEnvironmentApi(t *testing.T) { Resources: v1.ResourceRequirements{}, }, } - _, err := g.Client().V1().Environment().Get(&metav1.ObjectMeta{ + + restClient := rest.NewRESTClient("http://localhost:8888") + dClient := client.MakeClientset(restClient) + + _, err := dClient.V1().Environment().Get(&metav1.ObjectMeta{ Name: testEnv.ObjectMeta.Name, Namespace: testNS, }) assertNotFoundFailure(err, "environment") - m, err := g.Client().V1().Environment().Create(testEnv) + m, err := dClient.V1().Environment().Create(testEnv) panicIf(err) defer func() { - err := g.Client().V1().Environment().Delete(m) + err := dClient.V1().Environment().Delete(m) panicIf(err) }() - _, err = g.Client().V1().Environment().Create(testEnv) + _, err = dClient.V1().Environment().Create(testEnv) assertNameReuseFailure(err, "environment") - e, err := g.Client().V1().Environment().Get(m) + e, err := dClient.V1().Environment().Get(m) panicIf(err) assert(reflect.DeepEqual(testEnv.Spec, e.Spec), "env should match after reading") testEnv.ObjectMeta.ResourceVersion = m.ResourceVersion testEnv.Spec.Runtime.Image = "another-img" - _, err = g.Client().V1().Environment().Update(testEnv) + _, err = dClient.V1().Environment().Update(testEnv) panicIf(err) testEnv.ObjectMeta.ResourceVersion = "" testEnv.ObjectMeta.Name = "bar" - m2, err := g.Client().V1().Environment().Create(testEnv) + m2, err := dClient.V1().Environment().Create(testEnv) panicIf(err) defer func() { - err := g.Client().V1().Environment().Delete(m2) + err := dClient.V1().Environment().Delete(m2) panicIf(err) }() - ts, err := g.Client().V1().Environment().List(testNS) + ts, err := dClient.V1().Environment().List(testNS) panicIf(err) assert(len(ts) == 2, fmt.Sprintf("created two envs, but found %v", len(ts))) } @@ -379,23 +395,27 @@ func TestWatchApi(t *testing.T) { }, }, } - _, err := g.Client().V1().KubeWatcher().Get(&metav1.ObjectMeta{ + + restClient := rest.NewRESTClient("http://localhost:8888") + dClient := client.MakeClientset(restClient) + + _, err := dClient.V1().KubeWatcher().Get(&metav1.ObjectMeta{ Name: testWatch.ObjectMeta.Name, Namespace: testNS, }) assertNotFoundFailure(err, "watch") - m, err := g.Client().V1().KubeWatcher().Create(testWatch) + m, err := dClient.V1().KubeWatcher().Create(testWatch) panicIf(err) defer func() { - err := g.Client().V1().KubeWatcher().Delete(m) + err := dClient.V1().KubeWatcher().Delete(m) panicIf(err) }() - _, err = g.Client().V1().KubeWatcher().Create(testWatch) + _, err = dClient.V1().KubeWatcher().Create(testWatch) assertNameReuseFailure(err, "watch") - w, err := g.Client().V1().KubeWatcher().Get(m) + w, err := dClient.V1().KubeWatcher().Get(m) panicIf(err) assert(testWatch.Spec.Namespace == w.Spec.Namespace && testWatch.Spec.Type == w.Spec.Type && @@ -403,14 +423,14 @@ func TestWatchApi(t *testing.T) { testWatch.Spec.FunctionReference.Name == w.Spec.FunctionReference.Name, "watch should match after reading") testWatch.ObjectMeta.Name = "yyy" - m2, err := g.Client().V1().KubeWatcher().Create(testWatch) + m2, err := dClient.V1().KubeWatcher().Create(testWatch) panicIf(err) defer func() { - err := g.Client().V1().KubeWatcher().Delete(m2) + err := dClient.V1().KubeWatcher().Delete(m2) panicIf(err) }() - ws, err := g.Client().V1().KubeWatcher().List(testNS) + ws, err := dClient.V1().KubeWatcher().List(testNS) panicIf(err) assert(len(ws) == 2, fmt.Sprintf("created two watches, but found %v", len(ws))) } @@ -429,20 +449,24 @@ func TestTimeTriggerApi(t *testing.T) { }, }, } - _, err := g.Client().V1().TimeTrigger().Get(&metav1.ObjectMeta{Name: testTrigger.ObjectMeta.Name}) + + restClient := rest.NewRESTClient("http://localhost:8888") + dClient := client.MakeClientset(restClient) + + _, err := dClient.V1().TimeTrigger().Get(&metav1.ObjectMeta{Name: testTrigger.ObjectMeta.Name}) assertNotFoundFailure(err, "trigger") - m, err := g.Client().V1().TimeTrigger().Create(testTrigger) + m, err := dClient.V1().TimeTrigger().Create(testTrigger) panicIf(err) defer func() { - err := g.Client().V1().TimeTrigger().Delete(m) + err := dClient.V1().TimeTrigger().Delete(m) panicIf(err) }() - _, err = g.Client().V1().TimeTrigger().Create(testTrigger) + _, err = dClient.V1().TimeTrigger().Create(testTrigger) assertNameReuseFailure(err, "trigger") - tr, err := g.Client().V1().TimeTrigger().Get(m) + tr, err := dClient.V1().TimeTrigger().Get(m) panicIf(err) assert(testTrigger.Spec.Cron == tr.Spec.Cron && testTrigger.Spec.FunctionReference.Type == tr.Spec.FunctionReference.Type && @@ -450,16 +474,16 @@ func TestTimeTriggerApi(t *testing.T) { testTrigger.ObjectMeta.ResourceVersion = m.ResourceVersion testTrigger.Spec.Cron = "@hourly" - _, err = g.Client().V1().TimeTrigger().Update(testTrigger) + _, err = dClient.V1().TimeTrigger().Update(testTrigger) panicIf(err) testTrigger.ObjectMeta.ResourceVersion = "" testTrigger.ObjectMeta.Name = "yyy" testTrigger.Spec.Cron = "Not valid cron spec" - _, err = g.Client().V1().TimeTrigger().Create(testTrigger) + _, err = dClient.V1().TimeTrigger().Create(testTrigger) assertCronSpecFails(err) - ts, err := g.Client().V1().TimeTrigger().List(testNS) + ts, err := dClient.V1().TimeTrigger().List(testNS) panicIf(err) assert(len(ts) == 1, fmt.Sprintf("created two time triggers, but found %v", len(ts))) } @@ -497,9 +521,10 @@ func TestMain(m *testing.M) { time.Sleep(5 * time.Second) - restClient := rest.NewRESTClient("http://localhost:8888") + client, err := cmd.NewClient(cmd.ClientOptions{}) + panicIf(err) // TODO: use fake rest client for offline spec generation - cmd.SetClientset(client.MakeClientset(restClient)) + cmd.SetClientset(*client) resp, err := http.Get("http://localhost:8888/") panicIf(err) diff --git a/pkg/controller/client/v1/canaryconfig.go b/pkg/controller/client/v1/canaryconfig.go index 189bf3d4..bbe43412 100644 --- a/pkg/controller/client/v1/canaryconfig.go +++ b/pkg/controller/client/v1/canaryconfig.go @@ -20,11 +20,10 @@ import ( "encoding/json" "fmt" - "github.com/fission/fission/pkg/controller/client/rest" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" + "github.com/fission/fission/pkg/controller/client/rest" ) type ( diff --git a/pkg/controller/client/v1/fake/fake_package.go b/pkg/controller/client/v1/fake/fake_package.go index 9a4ade1c..01da4878 100644 --- a/pkg/controller/client/v1/fake/fake_package.go +++ b/pkg/controller/client/v1/fake/fake_package.go @@ -17,11 +17,10 @@ limitations under the License. package fake import ( - v1 "github.com/fission/fission/pkg/controller/client/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" + v1 "github.com/fission/fission/pkg/controller/client/v1" ) type ( diff --git a/pkg/controller/client/v1/fake/fake_timetrigger.go b/pkg/controller/client/v1/fake/fake_timetrigger.go index a1c6eb6f..05fe9b5c 100644 --- a/pkg/controller/client/v1/fake/fake_timetrigger.go +++ b/pkg/controller/client/v1/fake/fake_timetrigger.go @@ -17,11 +17,10 @@ limitations under the License. package fake import ( - v1 "github.com/fission/fission/pkg/controller/client/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" + v1 "github.com/fission/fission/pkg/controller/client/v1" ) type ( diff --git a/pkg/controller/client/v1/httptrigger.go b/pkg/controller/client/v1/httptrigger.go index ae1e3f74..e8f4d928 100644 --- a/pkg/controller/client/v1/httptrigger.go +++ b/pkg/controller/client/v1/httptrigger.go @@ -20,11 +20,10 @@ import ( "encoding/json" "fmt" - "github.com/fission/fission/pkg/controller/client/rest" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" + "github.com/fission/fission/pkg/controller/client/rest" ) type ( diff --git a/pkg/controller/client/v1/kuberneteswatchtrigger.go b/pkg/controller/client/v1/kuberneteswatchtrigger.go index 6f723646..91969d08 100644 --- a/pkg/controller/client/v1/kuberneteswatchtrigger.go +++ b/pkg/controller/client/v1/kuberneteswatchtrigger.go @@ -20,11 +20,10 @@ import ( "encoding/json" "fmt" - "github.com/fission/fission/pkg/controller/client/rest" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" + "github.com/fission/fission/pkg/controller/client/rest" ferror "github.com/fission/fission/pkg/error" ) diff --git a/pkg/controller/client/v1/mqtrigger.go b/pkg/controller/client/v1/mqtrigger.go index 02e28f7b..a391bf45 100644 --- a/pkg/controller/client/v1/mqtrigger.go +++ b/pkg/controller/client/v1/mqtrigger.go @@ -20,11 +20,10 @@ import ( "encoding/json" "fmt" - "github.com/fission/fission/pkg/controller/client/rest" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" + "github.com/fission/fission/pkg/controller/client/rest" ) type ( diff --git a/pkg/controller/client/v1/package.go b/pkg/controller/client/v1/package.go index 509646cb..70ec5be6 100644 --- a/pkg/controller/client/v1/package.go +++ b/pkg/controller/client/v1/package.go @@ -20,11 +20,10 @@ import ( "encoding/json" "fmt" - "github.com/fission/fission/pkg/controller/client/rest" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" + "github.com/fission/fission/pkg/controller/client/rest" ) type ( diff --git a/pkg/controller/client/v1/timetrigger.go b/pkg/controller/client/v1/timetrigger.go index 23688617..9e2f174c 100644 --- a/pkg/controller/client/v1/timetrigger.go +++ b/pkg/controller/client/v1/timetrigger.go @@ -20,11 +20,10 @@ import ( "encoding/json" "fmt" - "github.com/fission/fission/pkg/controller/client/rest" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" + "github.com/fission/fission/pkg/controller/client/rest" ) type ( diff --git a/pkg/controller/client/v1/v1.go b/pkg/controller/client/v1/v1.go index 7e7d1581..35d9a2be 100644 --- a/pkg/controller/client/v1/v1.go +++ b/pkg/controller/client/v1/v1.go @@ -20,9 +20,8 @@ import ( "io" "net/http" - ferror "github.com/fission/fission/pkg/error" - "github.com/fission/fission/pkg/controller/client/rest" + ferror "github.com/fission/fission/pkg/error" ) type ( diff --git a/pkg/fission-cli/cmd/archive/command.go b/pkg/fission-cli/cmd/archive/command.go index c1fdeb56..383253ef 100644 --- a/pkg/fission-cli/cmd/archive/command.go +++ b/pkg/fission-cli/cmd/archive/command.go @@ -32,7 +32,7 @@ func Commands() *cobra.Command { } wrapper.SetFlags(uploadCmd, flag.FlagSet{ Required: []flag.Flag{flag.ArchiveName}, - Optional: []flag.Flag{flag.KubeContext}, + Optional: []flag.Flag{}, }) listCmd := &cobra.Command{ @@ -41,7 +41,7 @@ func Commands() *cobra.Command { RunE: wrapper.Wrapper(List), } wrapper.SetFlags(listCmd, flag.FlagSet{ - Optional: []flag.Flag{flag.KubeContext}, + Optional: []flag.Flag{}, }) deleteCmd := &cobra.Command{ @@ -61,7 +61,7 @@ func Commands() *cobra.Command { } wrapper.SetFlags(geturlCmd, flag.FlagSet{ Required: []flag.Flag{flag.ArchiveID}, - Optional: []flag.Flag{flag.KubeContext}, + Optional: []flag.Flag{}, }) downloadCmd := &cobra.Command{ @@ -71,7 +71,7 @@ func Commands() *cobra.Command { } wrapper.SetFlags(downloadCmd, flag.FlagSet{ Required: []flag.Flag{flag.ArchiveID}, - Optional: []flag.Flag{flag.KubeContext, flag.ArchiveOutput}, + Optional: []flag.Flag{flag.ArchiveOutput}, }) command := &cobra.Command{ diff --git a/pkg/fission-cli/cmd/archive/delete.go b/pkg/fission-cli/cmd/archive/delete.go index dc195a5e..35e798cc 100644 --- a/pkg/fission-cli/cmd/archive/delete.go +++ b/pkg/fission-cli/cmd/archive/delete.go @@ -36,10 +36,9 @@ func Delete(input cli.Input) error { func (opts *DeleteSubCommand) do(input cli.Input) error { - kubeContext := input.String(flagkey.KubeContext) archiveID := input.String(flagkey.ArchiveID) - storagesvcURL, err := util.GetStorageURL(input.Context(), kubeContext) + storagesvcURL, err := util.GetStorageURL(input.Context(), opts.Client()) if err != nil { return err } diff --git a/pkg/fission-cli/cmd/archive/download.go b/pkg/fission-cli/cmd/archive/download.go index e64e3abf..3526dc54 100644 --- a/pkg/fission-cli/cmd/archive/download.go +++ b/pkg/fission-cli/cmd/archive/download.go @@ -37,7 +37,6 @@ func Download(input cli.Input) error { func (opts *DownloadSubCommand) do(input cli.Input) error { - kubeContext := input.String(flagkey.KubeContext) archiveID := input.String(flagkey.ArchiveID) archiveOutput := input.String(flagkey.ArchiveOutput) @@ -45,7 +44,7 @@ func (opts *DownloadSubCommand) do(input cli.Input) error { archiveOutput = strings.TrimPrefix(archiveID, "/fission/fission-functions/") } - storageAccessURL, err := util.GetStorageURL(input.Context(), kubeContext) + storageAccessURL, err := util.GetStorageURL(input.Context(), opts.Client()) if err != nil { return err } diff --git a/pkg/fission-cli/cmd/archive/geturl.go b/pkg/fission-cli/cmd/archive/geturl.go index 75c9acf8..e3cd1d04 100644 --- a/pkg/fission-cli/cmd/archive/geturl.go +++ b/pkg/fission-cli/cmd/archive/geturl.go @@ -38,10 +38,9 @@ func GetURL(input cli.Input) error { func (opts *GetURLSubCommand) do(input cli.Input) error { - kubeContext := input.String(flagkey.KubeContext) archiveID := input.String(flagkey.ArchiveID) - serverURL, err := util.GetStorageURL(input.Context(), kubeContext) + serverURL, err := util.GetStorageURL(input.Context(), opts.Client()) if err != nil { return err } @@ -67,7 +66,7 @@ func (opts *GetURLSubCommand) do(input cli.Input) error { storageType := resp.Header.Get("X-FISSION-STORAGETYPE") if storageType == "local" { - storageSvc, err := opts.Client().V1().Misc().GetSvcURL("application=fission-storage") + storageSvc, err := util.GetSvcName(input.Context(), opts.Client().KubernetesClient, "fission-storage") if err != nil { return err } diff --git a/pkg/fission-cli/cmd/archive/list.go b/pkg/fission-cli/cmd/archive/list.go index 4c1e18dc..78829bda 100644 --- a/pkg/fission-cli/cmd/archive/list.go +++ b/pkg/fission-cli/cmd/archive/list.go @@ -21,7 +21,6 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" - flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" "github.com/fission/fission/pkg/fission-cli/util" storagesvcClient "github.com/fission/fission/pkg/storagesvc/client" ) @@ -36,9 +35,7 @@ func List(input cli.Input) error { func (opts *ListSubCommand) do(input cli.Input) error { - kubeContext := input.String(flagkey.KubeContext) - - storageAccessURL, err := util.GetStorageURL(input.Context(), kubeContext) + storageAccessURL, err := util.GetStorageURL(input.Context(), opts.Client()) if err != nil { return err } diff --git a/pkg/fission-cli/cmd/archive/upload.go b/pkg/fission-cli/cmd/archive/upload.go index db231b57..3614b5c5 100644 --- a/pkg/fission-cli/cmd/archive/upload.go +++ b/pkg/fission-cli/cmd/archive/upload.go @@ -36,10 +36,9 @@ func Upload(input cli.Input) error { func (opts *UploadSubCommand) do(input cli.Input) error { - kubeContext := input.String(flagkey.KubeContext) archiveName := input.String(flagkey.ArchiveName) - storagesvcURL, err := util.GetStorageURL(input.Context(), kubeContext) + storagesvcURL, err := util.GetStorageURL(input.Context(), opts.Client()) if err != nil { return err } diff --git a/pkg/fission-cli/cmd/canaryconfig/create.go b/pkg/fission-cli/cmd/canaryconfig/create.go index a97ee0ba..35d75561 100644 --- a/pkg/fission-cli/cmd/canaryconfig/create.go +++ b/pkg/fission-cli/cmd/canaryconfig/create.go @@ -54,7 +54,8 @@ func (opts *CreateSubCommand) complete(input cli.Input) (err error) { ht := input.String(flagkey.CanaryHTTPTriggerName) newFunc := input.String(flagkey.CanaryNewFunc) oldFunc := input.String(flagkey.CanaryOldFunc) - _, fnNs, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + + _, fnNs, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in creating canaryconfig") } @@ -69,10 +70,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) (err error) { } // check that the trigger exists in the same namespace. - htTrigger, err := opts.Client().V1().HTTPTrigger().Get(&metav1.ObjectMeta{ - Name: ht, - Namespace: fnNs, - }) + htTrigger, err := opts.Client().FissionClientSet.CoreV1().HTTPTriggers(fnNs).Get(input.Context(), ht, metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error finding http trigger referenced in the canary config") } @@ -95,7 +93,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) (err error) { // check that the functions exist in the same namespace fnList := []string{newFunc, oldFunc} - err = util.CheckFunctionExistence(opts.Client(), fnList, fnNs) + err = util.CheckFunctionExistence(input.Context(), opts.Client(), fnList, fnNs) if err != nil { return errors.Wrap(err, "error checking functions existence") } @@ -124,7 +122,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) (err error) { } func (opts *CreateSubCommand) run(input cli.Input) error { - _, err := opts.Client().V1().CanaryConfig().Create(opts.canary) + _, err := opts.Client().FissionClientSet.CoreV1().CanaryConfigs(opts.canary.ObjectMeta.Namespace).Create(input.Context(), opts.canary, metav1.CreateOptions{}) if err != nil { return errors.Wrap(err, "error creating canary config") } diff --git a/pkg/fission-cli/cmd/canaryconfig/delete.go b/pkg/fission-cli/cmd/canaryconfig/delete.go index e50f8228..c9cd088a 100644 --- a/pkg/fission-cli/cmd/canaryconfig/delete.go +++ b/pkg/fission-cli/cmd/canaryconfig/delete.go @@ -37,16 +37,12 @@ func Delete(input cli.Input) error { } func (opts *DeleteSubCommand) run(input cli.Input) (err error) { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceCanary) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceCanary) if err != nil { return errors.Wrap(err, "error in deleting canaryConfig ") } - m := &metav1.ObjectMeta{ - Name: input.String(flagkey.CanaryName), - Namespace: namespace, - } - err = opts.Client().V1().CanaryConfig().Delete(m) + err = opts.Client().FissionClientSet.CoreV1().CanaryConfigs(namespace).Delete(input.Context(), input.String(flagkey.CanaryName), metav1.DeleteOptions{}) if err != nil { if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { return nil @@ -54,6 +50,6 @@ func (opts *DeleteSubCommand) run(input cli.Input) (err error) { return errors.Wrap(err, "error deleting canary config") } - fmt.Printf("canaryconfig '%v.%v' deleted\n", m.Name, m.Namespace) + fmt.Printf("canaryconfig '%v.%v' deleted\n", input.String(flagkey.CanaryName), namespace) return nil } diff --git a/pkg/fission-cli/cmd/canaryconfig/get.go b/pkg/fission-cli/cmd/canaryconfig/get.go index dd773f88..3a34ec84 100644 --- a/pkg/fission-cli/cmd/canaryconfig/get.go +++ b/pkg/fission-cli/cmd/canaryconfig/get.go @@ -27,7 +27,6 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type GetSubCommand struct { @@ -40,15 +39,12 @@ func Get(input cli.Input) error { func (opts *GetSubCommand) run(input cli.Input) (err error) { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceCanary) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceCanary) if err != nil { return errors.Wrap(err, "error getting canary config") } - canaryCfg, err := opts.Client().V1().CanaryConfig().Get(&metav1.ObjectMeta{ - Name: input.String(flagkey.CanaryName), - Namespace: namespace, - }) + canaryCfg, err := opts.Client().FissionClientSet.CoreV1().CanaryConfigs(namespace).Get(input.Context(), input.String(flagkey.CanaryName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting canary config") } diff --git a/pkg/fission-cli/cmd/canaryconfig/list.go b/pkg/fission-cli/cmd/canaryconfig/list.go index 86cb5782..c4cb6d60 100644 --- a/pkg/fission-cli/cmd/canaryconfig/list.go +++ b/pkg/fission-cli/cmd/canaryconfig/list.go @@ -22,12 +22,11 @@ import ( "text/tabwriter" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -48,7 +47,7 @@ func (opts *ListSubCommand) do(input cli.Input) error { } func (opts *ListSubCommand) complete(input cli.Input) (err error) { - _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespaceCanary) + _, opts.namespace, err = opts.GetResourceNamespace(input, flagkey.NamespaceCanary) if err != nil { return errors.Wrap(err, "error in listing canary config ") } @@ -57,19 +56,18 @@ func (opts *ListSubCommand) complete(input cli.Input) (err error) { func (opts *ListSubCommand) run(input cli.Input) (err error) { - var canaryCfgs []v1.CanaryConfig if input.Bool(flagkey.AllNamespaces) { - canaryCfgs, err = opts.Client().V1().CanaryConfig().List("") - } else { - canaryCfgs, err = opts.Client().V1().CanaryConfig().List(opts.namespace) + opts.namespace = metav1.NamespaceAll } + canaryCfgs, err := opts.Client().FissionClientSet.CoreV1().CanaryConfigs(opts.namespace).List(input.Context(), metav1.ListOptions{}) + if err != nil { return errors.Wrap(err, "error listing canary config") } w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", "NAME", "TRIGGER", "FUNCTION-N", "FUNCTION-N-1", "WEIGHT-INCREMENT", "INTERVAL", "FAILURE-THRESHOLD", "FAILURE-TYPE", "STATUS") - for _, canaryCfg := range canaryCfgs { + for _, canaryCfg := range canaryCfgs.Items { fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", canaryCfg.ObjectMeta.Name, canaryCfg.Spec.Trigger, canaryCfg.Spec.NewFunction, canaryCfg.Spec.OldFunction, canaryCfg.Spec.WeightIncrement, canaryCfg.Spec.WeightIncrementDuration, canaryCfg.Spec.FailureThreshold, canaryCfg.Spec.FailureType, canaryCfg.Status.Status) diff --git a/pkg/fission-cli/cmd/canaryconfig/update.go b/pkg/fission-cli/cmd/canaryconfig/update.go index 513e9244..808fe0a0 100644 --- a/pkg/fission-cli/cmd/canaryconfig/update.go +++ b/pkg/fission-cli/cmd/canaryconfig/update.go @@ -27,7 +27,6 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type UpdateSubCommand struct { @@ -49,8 +48,7 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { // get the current config - name := input.String(flagkey.CanaryName) - _, ns, err := util.GetResourceNamespace(input, flagkey.NamespaceCanary) + _, ns, err := opts.GetResourceNamespace(input, flagkey.NamespaceCanary) if err != nil { return errors.Wrap(err, "error updating canary config") } @@ -64,10 +62,7 @@ func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { return errors.Wrap(err, "error parsing time duration") } - canaryCfg, err := opts.Client().V1().CanaryConfig().Get(&metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }) + canaryCfg, err := opts.Client().FissionClientSet.CoreV1().CanaryConfigs(ns).Get(input.Context(), input.String(flagkey.CanaryName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting canary config") } @@ -96,7 +91,7 @@ func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { } func (opts *UpdateSubCommand) run(input cli.Input) error { - _, err := opts.Client().V1().CanaryConfig().Update(opts.canary) + _, err := opts.Client().FissionClientSet.CoreV1().CanaryConfigs(opts.canary.ObjectMeta.Namespace).Update(input.Context(), opts.canary, metav1.UpdateOptions{}) if err != nil { return errors.Wrap(err, "error updating canary config") } diff --git a/pkg/fission-cli/cmd/check/check.go b/pkg/fission-cli/cmd/check/check.go index c74df766..43717577 100644 --- a/pkg/fission-cli/cmd/check/check.go +++ b/pkg/fission-cli/cmd/check/check.go @@ -30,8 +30,6 @@ func Check(input cli.Input) error { func (opts *CheckSubCommand) do(input cli.Input) error { - kubeContext := input.String(flagkey.KubeContext) - checks := []healthcheck.CategoryID{} if input.IsSet(flagkey.PreCheckOnly) { @@ -40,11 +38,8 @@ func (opts *CheckSubCommand) do(input cli.Input) error { checks = append(checks, healthcheck.FissionServices, healthcheck.FissionVersion) } - hc := healthcheck.NewHealthChecker(checks, &healthcheck.Options{ - KubeContext: kubeContext, - FissionClient: opts.Client(), - }) + hc := healthcheck.NewHealthChecker(opts.Client(), checks) - healthcheck.RunChecks(input.Context(), hc) + healthcheck.RunChecks(input.Context(), input, opts.Client(), hc) return nil } diff --git a/pkg/fission-cli/cmd/client.go b/pkg/fission-cli/cmd/client.go new file mode 100644 index 00000000..b00dd662 --- /dev/null +++ b/pkg/fission-cli/cmd/client.go @@ -0,0 +1,134 @@ +/* +Copyright 2022 The Fission 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 cmd + +import ( + "errors" + "fmt" + "os" + "os/user" + "path/filepath" + + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + + "github.com/fission/fission/pkg/fission-cli/console" + "github.com/fission/fission/pkg/generated/clientset/versioned" +) + +type ( + ClientOptions struct { + KubeContext string + } + Client struct { + Options ClientOptions + ClientConfig clientcmd.ClientConfig + RestConfig *rest.Config + FissionClientSet versioned.Interface + KubernetesClient kubernetes.Interface + Namespace string + } +) + +func (c *Client) SetFissionClientset(fissionClientSet versioned.Interface) { + c.FissionClientSet = fissionClientSet +} + +func (c *Client) SetKubernetesClient(kubernetesClient kubernetes.Interface) { + c.KubernetesClient = kubernetesClient +} + +func getLoadingRules() (loadingRules *clientcmd.ClientConfigLoadingRules, err error) { + loadingRules = clientcmd.NewDefaultClientConfigLoadingRules() + + kubeConfigPath := os.Getenv("KUBECONFIG") + if len(kubeConfigPath) == 0 { + var homeDir string + usr, err := user.Current() + if err != nil { + // In case that user.Current() may be unable to work under some circumstances and return errors like + // "user: Current not implemented on darwin/amd64" due to cross-compilation problem. (https://github.com/golang/go/issues/6376). + // Instead of doing fatal here, we fallback to get home directory from the environment $HOME. + console.Warn(fmt.Sprintf("Could not get the current user's directory (%s), fallback to get it from env $HOME", err)) + homeDir = os.Getenv("HOME") + } else { + homeDir = usr.HomeDir + } + kubeConfigPath = filepath.Join(homeDir, ".kube", "config") + + if _, err := os.Stat(kubeConfigPath); os.IsNotExist(err) { + return nil, errors.New("couldn't find kubeconfig file. " + + "Set the KUBECONFIG environment variable to your kubeconfig's path.") + } + loadingRules.ExplicitPath = kubeConfigPath + console.Verbose(2, "Using kubeconfig from %q", kubeConfigPath) + } else { + console.Verbose(2, "Using kubeconfig from environment %q", kubeConfigPath) + } + return loadingRules, nil +} + +func GetClientConfig(kubeContext string) (clientcmd.ClientConfig, error) { + loadingRules, err := getLoadingRules() + if err != nil { + return nil, err + } + overrides := &clientcmd.ConfigOverrides{} + if len(kubeContext) > 0 { + console.Verbose(2, "Using kubeconfig context %q", kubeContext) + overrides.CurrentContext = kubeContext + } + return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides), nil +} + +func NewClient(opts ClientOptions) (*Client, error) { + client := &Client{ + Options: opts, + } + cmdConfig, err := GetClientConfig(opts.KubeContext) + if err != nil { + return nil, err + } + client.ClientConfig = cmdConfig + + namespace, _, err := cmdConfig.Namespace() + if err != nil { + return nil, err + } + client.Namespace = namespace + console.Verbose(2, "Kubeconfig default namespace %q", namespace) + + restConfig, err := cmdConfig.ClientConfig() + if err != nil { + return nil, err + } + client.RestConfig = restConfig + clientset, err := kubernetes.NewForConfig(restConfig) + if err != nil { + return nil, err + } + client.KubernetesClient = clientset + + fissionClientset, err := versioned.NewForConfig(restConfig) + if err != nil { + return nil, err + } + client.FissionClientSet = fissionClientset + + return client, nil +} diff --git a/pkg/fission-cli/cmd/cmd.go b/pkg/fission-cli/cmd/cmd.go index 599ee831..23f128fa 100644 --- a/pkg/fission-cli/cmd/cmd.go +++ b/pkg/fission-cli/cmd/cmd.go @@ -17,10 +17,12 @@ limitations under the License. package cmd import ( + "os" "sync" - "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" + "github.com/fission/fission/pkg/fission-cli/console" + flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" ) type ( @@ -29,16 +31,40 @@ type ( ) var ( - once = sync.Once{} - defaultClientset client.Interface + once = sync.Once{} + defaultClient Client ) -func SetClientset(clientset client.Interface) { +func SetClientset(client Client) { once.Do(func() { - defaultClientset = clientset + defaultClient = client }) } -func (c *CommandActioner) Client() client.Interface { - return defaultClientset +func (c *CommandActioner) Client() Client { + return defaultClient +} + +func (c *CommandActioner) GetResourceNamespace(input cli.Input, deprecatedFlag string) (namespace, currentNS string, err error) { + namespace = input.String(deprecatedFlag) + currentNS = namespace + + if input.String(flagkey.Namespace) != "" { + namespace = input.String(flagkey.Namespace) + currentNS = namespace + console.Verbose(2, "Namespace for resource %s ", currentNS) + return namespace, currentNS, err + } + + if namespace == "" { + if os.Getenv("FISSION_DEFAULT_NAMESPACE") != "" { + currentNS = os.Getenv("FISSION_DEFAULT_NAMESPACE") + } else { + currentNS = c.Client().Namespace + return namespace, currentNS, err + } + } + + console.Verbose(2, "Namespace for resource %s ", currentNS) + return namespace, currentNS, nil } diff --git a/pkg/fission-cli/cmd/environment/create.go b/pkg/fission-cli/cmd/environment/create.go index d631aaa1..e0e38176 100644 --- a/pkg/fission-cli/cmd/environment/create.go +++ b/pkg/fission-cli/cmd/environment/create.go @@ -66,16 +66,16 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { func (opts *CreateSubCommand) run(input cli.Input) (err error) { m := opts.env.ObjectMeta - envList, err := opts.Client().V1().Environment().List(m.Namespace) + envList, err := opts.Client().FissionClientSet.CoreV1().Environments(m.Namespace).List(input.Context(), metav1.ListOptions{}) if err != nil { return err - } else if len(envList) > 0 { + } else if len(envList.Items) > 0 { console.Verbose(2, "%d environment(s) are present in the %s namespace. "+ "These environments are not isolated from each other; use separate namespaces if you need isolation.", - len(envList), m.Namespace) + len(envList.Items), m.Namespace) } - userDefinedNS, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + userDefinedNS, currentNS, err := opts.GetResourceNamespace(input, flagkey.NamespaceEnvironment) if err != nil { return fv1.AggregateValidationErrors("Environment", err) } @@ -108,14 +108,10 @@ func (opts *CreateSubCommand) run(input cli.Input) (err error) { } opts.env.ObjectMeta.Namespace = currentNS - err = opts.env.Validate() - if err != nil { - return fv1.AggregateValidationErrors("Environment", err) - } - _, err = opts.Client().V1().Environment().Create(opts.env) + _, err = opts.Client().FissionClientSet.CoreV1().Environments(opts.env.Namespace).Create(input.Context(), opts.env, metav1.CreateOptions{}) if err != nil { - return errors.Wrap(err, "error creating environment") + return errors.Wrap(err, "error creating resource") } fmt.Printf("environment '%v' created\n", m.Name) diff --git a/pkg/fission-cli/cmd/environment/delete.go b/pkg/fission-cli/cmd/environment/delete.go index f7b5b751..374ea5b9 100644 --- a/pkg/fission-cli/cmd/environment/delete.go +++ b/pkg/fission-cli/cmd/environment/delete.go @@ -20,13 +20,13 @@ import ( "fmt" "github.com/pkg/errors" + kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/console" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type DeleteSubCommand struct { @@ -39,40 +39,36 @@ func Delete(input cli.Input) error { func (opts *DeleteSubCommand) do(input cli.Input) (err error) { - _, currentContextNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + _, currentContextNS, err := opts.GetResourceNamespace(input, flagkey.NamespaceEnvironment) if err != nil { return errors.Wrap(err, "error creating environment") } console.Verbose(2, "Searching for resource in %s Namespace", currentContextNS) - - m := &metav1.ObjectMeta{ - Name: input.String(flagkey.EnvName), - Namespace: currentContextNS, - } + envName := input.String(flagkey.EnvName) if !input.Bool(flagkey.EnvForce) { - fns, err := opts.Client().V1().Function().List(metav1.NamespaceAll) + fns, err := opts.Client().FissionClientSet.CoreV1().Functions(metav1.NamespaceAll).List(input.Context(), metav1.ListOptions{}) if err != nil { return errors.Wrap(err, "Error getting functions wrt environment.") } - for _, fn := range fns { - if fn.Spec.Environment.Name == m.Name && - fn.Spec.Environment.Namespace == m.Namespace { + for _, fn := range fns.Items { + if fn.Spec.Environment.Name == envName && + fn.Spec.Environment.Namespace == currentContextNS { return errors.New("Environment is used by at least one function.") } } } - err = opts.Client().V1().Environment().Delete(m) + err = opts.Client().FissionClientSet.CoreV1().Environments(currentContextNS).Delete(input.Context(), envName, metav1.DeleteOptions{}) if err != nil { - if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { + if input.Bool(flagkey.IgnoreNotFound) && kerrors.IsNotFound(err) { return nil } return errors.Wrap(err, "error deleting environment") } - fmt.Printf("environment '%v' deleted\n", m.Name) + fmt.Printf("environment '%s' deleted\n", envName) return nil } diff --git a/pkg/fission-cli/cmd/environment/get.go b/pkg/fission-cli/cmd/environment/get.go index 4c72bdbf..8b969d08 100644 --- a/pkg/fission-cli/cmd/environment/get.go +++ b/pkg/fission-cli/cmd/environment/get.go @@ -27,7 +27,6 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type GetSubCommand struct { @@ -40,17 +39,12 @@ func Get(input cli.Input) error { func (opts *GetSubCommand) do(input cli.Input) (err error) { - _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + _, currentNS, err := opts.GetResourceNamespace(input, flagkey.NamespaceEnvironment) if err != nil { return errors.Wrap(err, "error creating environment") } - m := &metav1.ObjectMeta{ - Name: input.String(flagkey.EnvName), - Namespace: currentNS, - } - - env, err := opts.Client().V1().Environment().Get(m) + env, err := opts.Client().FissionClientSet.CoreV1().Environments(currentNS).Get(input.Context(), input.String(flagkey.EnvName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting environment") } diff --git a/pkg/fission-cli/cmd/environment/list.go b/pkg/fission-cli/cmd/environment/list.go index 383f43e9..8300db23 100644 --- a/pkg/fission-cli/cmd/environment/list.go +++ b/pkg/fission-cli/cmd/environment/list.go @@ -22,12 +22,11 @@ import ( "text/tabwriter" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -40,22 +39,22 @@ func List(input cli.Input) error { func (opts *ListSubCommand) do(input cli.Input) (err error) { - _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + _, currentNS, err := opts.GetResourceNamespace(input, flagkey.NamespaceEnvironment) if err != nil { return errors.Wrap(err, "error creating environment") } - var envs []v1.Environment if input.Bool(flagkey.AllNamespaces) { - envs, err = opts.Client().V1().Environment().List("") - } else { - envs, err = opts.Client().V1().Environment().List(currentNS) + currentNS = metav1.NamespaceAll } + response, err := opts.Client().FissionClientSet.CoreV1().Environments(currentNS).List(input.Context(), metav1.ListOptions{}) if err != nil { return errors.Wrap(err, "error listing environments") } + envs := response.Items + w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", "NAME", "IMAGE", "BUILDER_IMAGE", "POOLSIZE", "MINCPU", "MAXCPU", "MINMEMORY", "MAXMEMORY", "EXTNET", "GRACETIME", "NAMESPACE") for _, env := range envs { diff --git a/pkg/fission-cli/cmd/environment/pods.go b/pkg/fission-cli/cmd/environment/pods.go index b536684b..2eca539c 100644 --- a/pkg/fission-cli/cmd/environment/pods.go +++ b/pkg/fission-cli/cmd/environment/pods.go @@ -23,12 +23,12 @@ import ( "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" "github.com/fission/fission/pkg/utils" ) @@ -42,37 +42,35 @@ func ListPods(input cli.Input) error { func (opts *ListPodsSubCommand) do(input cli.Input) (err error) { - _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + _, currentNS, err := opts.GetResourceNamespace(input, flagkey.NamespaceEnvironment) if err != nil { return errors.Wrap(err, "error creating environment") } - // validate environment - _, err = opts.Client().V1().Environment().Get( - &metav1.ObjectMeta{ - Name: input.String(flagkey.EnvName), - Namespace: currentNS, - }) + _, err = opts.Client().FissionClientSet.CoreV1().Environments(currentNS).Get(input.Context(), input.String(flagkey.EnvName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting environment") } - m := &metav1.ObjectMeta{ - Name: input.String(flagkey.EnvName), - Labels: map[string]string{ - v1.ENVIRONMENT_NAMESPACE: currentNS, - v1.EXECUTOR_TYPE: input.String(flagkey.EnvExecutorType), - }, + // label selector + selector := map[string]string{ + v1.ENVIRONMENT_NAME: input.String(flagkey.EnvName), + } + selector[v1.ENVIRONMENT_NAMESPACE] = currentNS + if len(input.String(flagkey.EnvExecutorType)) > 0 { + selector[v1.EXECUTOR_TYPE] = input.String(flagkey.EnvExecutorType) } - pods, err := opts.Client().V1().Environment().ListPods(m) + podsList, err := opts.Client().KubernetesClient.CoreV1().Pods(metav1.NamespaceAll).List(input.Context(), metav1.ListOptions{ + LabelSelector: labels.Set(selector).AsSelector().String(), + }) if err != nil { return errors.Wrap(err, "error listing environments") } w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t\n", "NAME", "NAMESPACE", "READY", "STATUS", "IP", "EXECUTORTYPE", "MANAGED") - for _, pod := range pods { + for _, pod := range podsList.Items { // A deletion timestamp indicates that a pod is terminating. Do not count this pod. if pod.ObjectMeta.DeletionTimestamp != nil { diff --git a/pkg/fission-cli/cmd/environment/update.go b/pkg/fission-cli/cmd/environment/update.go index 5ac7a23b..ea89791a 100644 --- a/pkg/fission-cli/cmd/environment/update.go +++ b/pkg/fission-cli/cmd/environment/update.go @@ -54,14 +54,11 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { - _, currentContextNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + _, currentContextNS, err := opts.GetResourceNamespace(input, flagkey.NamespaceEnvironment) if err != nil { return errors.Wrap(err, "error creating environment") } - env, err := opts.Client().V1().Environment().Get(&metav1.ObjectMeta{ - Name: input.String(flagkey.EnvName), - Namespace: currentContextNS, - }) + env, err := opts.Client().FissionClientSet.CoreV1().Environments(currentContextNS).Get(input.Context(), input.String(flagkey.EnvName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error finding environment") } @@ -81,12 +78,16 @@ func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { } func (opts *UpdateSubCommand) run(input cli.Input) error { - _, err := opts.Client().V1().Environment().Update(opts.env) + + enew, err := opts.Client().FissionClientSet.CoreV1().Environments(opts.env.ObjectMeta.Namespace).Update(input.Context(), opts.env, metav1.UpdateOptions{}) + if err != nil { + return errors.Wrap(err, "error updating environment") + } if err != nil { return errors.Wrap(err, "error updating environment") } - fmt.Printf("environment '%v' updated\n", opts.env.ObjectMeta.Name) + fmt.Printf("environment '%v' updated\n", enew.ObjectMeta.Name) return nil } diff --git a/pkg/fission-cli/cmd/function/create.go b/pkg/fission-cli/cmd/function/create.go index 8959b3c2..0b6e3e5d 100644 --- a/pkg/fission-cli/cmd/function/create.go +++ b/pkg/fission-cli/cmd/function/create.go @@ -65,7 +65,7 @@ func (opts *CreateSubCommand) do(input cli.Input) error { func (opts *CreateSubCommand) complete(input cli.Input) error { fnName := input.String(flagkey.FnName) - userProvidedNS, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + userProvidedNS, fnNamespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error retrieving namespace information") } @@ -81,13 +81,10 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { if !toSpec { // check for unique function names within a namespace - fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ - Name: input.String(flagkey.FnName), - Namespace: fnNamespace, - }) - if err != nil && !ferror.IsNotFound(err) { + fn, err := opts.Client().FissionClientSet.CoreV1().Functions(fnNamespace).Get(input.Context(), input.String(flagkey.FnName), metav1.GetOptions{}) + if err != nil && !k8serrors.IsNotFound(err) { return err - } else if fn != nil { + } else if fn.Name != "" && fn.Namespace != "" { return errors.New("a function with the same name already exists") } } @@ -155,10 +152,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { pkgMetadata = &pkg.ObjectMeta } else { // use existing package - pkg, err = opts.Client().V1().Package().Get(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: pkgName, - }) + pkg, err = opts.Client().FissionClientSet.CoreV1().Packages(fnNamespace).Get(input.Context(), pkgName, metav1.GetOptions{}) if err != nil { return errors.Wrap(err, fmt.Sprintf("read package in '%s' in Namespace: %s. Package needs to be present in the same namespace as function", pkgName, fnNamespace)) } @@ -196,10 +190,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { fnName, envName)) } } else { - _, err := opts.Client().V1().Environment().Get(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: envName, - }) + _, err := opts.Client().FissionClientSet.CoreV1().Environments(fnNamespace).Get(input.Context(), envName, metav1.GetOptions{}) if err != nil { if e, ok := err.(ferror.Error); ok && e.Code == ferror.ErrorNotFound { console.Warn(fmt.Sprintf("Environment \"%s\" does not exist. Please create the environment before executing the function. \nFor example: `fission env create --name %s --envns %s --image `\n", envName, envName, fnNamespace)) @@ -246,10 +237,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { // check the referenced secret is in the same ns as the function, if not give a warning. if !toSpec { // TODO: workaround in order not to block users from creating function spec, remove it. for _, secretName := range secretNames { - err := opts.Client().V1().Misc().SecretExists(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: secretName, - }) + err := util.SecretExists(input.Context(), &metav1.ObjectMeta{Namespace: fnNamespace, Name: secretName}, opts.Client().KubernetesClient) if err != nil { if k8serrors.IsNotFound(err) { console.Warn(fmt.Sprintf("Secret %s not found in Namespace: %s. Secret needs to be present in the same namespace as function", secretName, fnNamespace)) @@ -279,10 +267,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { // check the referenced cfgmap is in the same ns as the function, if not give a warning. if !toSpec { for _, cfgMapName := range cfgMapNames { - err := opts.Client().V1().Misc().ConfigMapExists(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: cfgMapName, - }) + err := util.ConfigMapExists(input.Context(), &metav1.ObjectMeta{Namespace: fnNamespace, Name: cfgMapName}, opts.Client().KubernetesClient) if err != nil { if k8serrors.IsNotFound(err) { console.Warn(fmt.Sprintf("ConfigMap %s not found in Namespace: %s. ConfigMap needs to be present in the same namespace as function", cfgMapName, fnNamespace)) @@ -385,7 +370,7 @@ func (opts *CreateSubCommand) run(input cli.Input) error { return nil } - _, err := opts.Client().V1().Function().Create(opts.function) + _, err := opts.Client().FissionClientSet.CoreV1().Functions(opts.function.ObjectMeta.Namespace).Create(input.Context(), opts.function, metav1.CreateOptions{}) if err != nil { return errors.Wrap(err, "error creating function") } @@ -434,7 +419,7 @@ func (opts *CreateSubCommand) run(input cli.Input) error { }, }, } - _, err = opts.Client().V1().HTTPTrigger().Create(ht) + _, err = opts.Client().FissionClientSet.CoreV1().HTTPTriggers(opts.function.ObjectMeta.Namespace).Create(input.Context(), ht, metav1.CreateOptions{}) if err != nil { return errors.Wrap(err, "error creating HTTP trigger") } diff --git a/pkg/fission-cli/cmd/function/delete.go b/pkg/fission-cli/cmd/function/delete.go index e0095dda..2f2d1fb2 100644 --- a/pkg/fission-cli/cmd/function/delete.go +++ b/pkg/fission-cli/cmd/function/delete.go @@ -38,7 +38,7 @@ func Delete(input cli.Input) error { func (opts *DeleteSubCommand) do(input cli.Input) error { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in deleting function ") } @@ -47,7 +47,7 @@ func (opts *DeleteSubCommand) do(input cli.Input) error { Namespace: namespace, } - err = opts.Client().V1().Function().Delete(m) + err = opts.Client().FissionClientSet.CoreV1().Functions(namespace).Delete(input.Context(), input.String(flagkey.FnName), metav1.DeleteOptions{}) if err != nil { if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { return nil diff --git a/pkg/fission-cli/cmd/function/get.go b/pkg/fission-cli/cmd/function/get.go index af48081a..25135b93 100644 --- a/pkg/fission-cli/cmd/function/get.go +++ b/pkg/fission-cli/cmd/function/get.go @@ -25,7 +25,6 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type GetSubCommand struct { @@ -37,22 +36,16 @@ func Get(input cli.Input) error { } func (opts *GetSubCommand) do(input cli.Input) error { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in get function ") } - fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ - Name: input.String(flagkey.FnName), - Namespace: namespace, - }) + fn, err := opts.Client().FissionClientSet.CoreV1().Functions(namespace).Get(input.Context(), input.String(flagkey.FnName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting function") } - pkg, err := opts.Client().V1().Package().Get(&metav1.ObjectMeta{ - Name: fn.Spec.Package.PackageRef.Name, - Namespace: fn.Spec.Package.PackageRef.Namespace, - }) + pkg, err := opts.Client().FissionClientSet.CoreV1().Packages(fn.Spec.Package.PackageRef.Namespace).Get(input.Context(), fn.Spec.Package.PackageRef.Name, metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting package") } diff --git a/pkg/fission-cli/cmd/function/getmeta.go b/pkg/fission-cli/cmd/function/getmeta.go index 02c67ca9..936fa5ef 100644 --- a/pkg/fission-cli/cmd/function/getmeta.go +++ b/pkg/fission-cli/cmd/function/getmeta.go @@ -25,7 +25,6 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type GetMetaSubCommand struct { @@ -37,15 +36,12 @@ func GetMeta(input cli.Input) error { } func (opts *GetMetaSubCommand) do(input cli.Input) error { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in getting meta function ") } - fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ - Name: input.String(flagkey.FnName), - Namespace: namespace, - }) + fn, err := opts.Client().FissionClientSet.CoreV1().Functions(namespace).Get(input.Context(), input.String(flagkey.FnName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting function") } diff --git a/pkg/fission-cli/cmd/function/list.go b/pkg/fission-cli/cmd/function/list.go index 98a3662d..5ef7a7ce 100644 --- a/pkg/fission-cli/cmd/function/list.go +++ b/pkg/fission-cli/cmd/function/list.go @@ -23,12 +23,11 @@ import ( "text/tabwriter" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -40,17 +39,16 @@ func List(input cli.Input) error { } func (opts *ListSubCommand) do(input cli.Input) error { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in listing function ") } - var fns []v1.Function if input.Bool(flagkey.AllNamespaces) { - fns, err = opts.Client().V1().Function().List("") - } else { - fns, err = opts.Client().V1().Function().List(namespace) + namespace = metav1.NamespaceAll } + fns, err := opts.Client().FissionClientSet.CoreV1().Functions(namespace).List(input.Context(), metav1.ListOptions{}) + if err != nil { return errors.Wrap(err, "error listing functions") } @@ -58,7 +56,7 @@ func (opts *ListSubCommand) do(input cli.Input) error { w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", "NAME", "ENV", "EXECUTORTYPE", "MINSCALE", "MAXSCALE", "MINCPU", "MAXCPU", "MINMEMORY", "MAXMEMORY", "SECRETS", "CONFIGMAPS", "NAMESPACE") - for _, f := range fns { + for _, f := range fns.Items { secrets := f.Spec.Secrets configMaps := f.Spec.ConfigMaps var secretsList, configMapList []string diff --git a/pkg/fission-cli/cmd/function/log.go b/pkg/fission-cli/cmd/function/log.go index b1a187db..7bcffa66 100644 --- a/pkg/fission-cli/cmd/function/log.go +++ b/pkg/fission-cli/cmd/function/log.go @@ -40,14 +40,13 @@ func Log(input cli.Input) error { } func (opts *LogSubCommand) do(input cli.Input) error { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in logs for function ") } dbType := input.String(flagkey.FnLogDBType) fnPod := input.String(flagkey.FnLogPod) - kubeContext := input.String(flagkey.KubeContext) logReverseQuery := !input.Bool(flagkey.FnLogFollow) && input.Bool(flagkey.FnLogReverseQuery) @@ -56,15 +55,12 @@ func (opts *LogSubCommand) do(input cli.Input) error { recordLimit = 1000 } - f, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ - Name: input.String(flagkey.FnName), - Namespace: namespace, - }) + f, err := opts.Client().FissionClientSet.CoreV1().Functions(namespace).Get(input.Context(), input.String(flagkey.FnName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting function") } - server, err := util.GetApplicationUrl(input.Context(), "application=fission-api", kubeContext) + server, err := util.GetApplicationUrl(input.Context(), opts.Client(), "application=fission-api") if err != nil { return err } diff --git a/pkg/fission-cli/cmd/function/pods.go b/pkg/fission-cli/cmd/function/pods.go index 0f6835ec..5bfe8138 100644 --- a/pkg/fission-cli/cmd/function/pods.go +++ b/pkg/fission-cli/cmd/function/pods.go @@ -23,12 +23,12 @@ import ( "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" "github.com/fission/fission/pkg/utils" ) @@ -42,35 +42,34 @@ func ListPods(input cli.Input) error { func (opts *ListPodsSubCommand) do(input cli.Input) error { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in finding pod for function ") } // validate function - _, err = opts.Client().V1().Function().Get(&metav1.ObjectMeta{ - Name: input.String(flagkey.FnName), - Namespace: namespace, - }) + _, err = opts.Client().FissionClientSet.CoreV1().Functions(namespace).Get(input.Context(), input.String(flagkey.FnName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting function") } - m := &metav1.ObjectMeta{ - Name: input.String(flagkey.FnName), - Labels: map[string]string{ - v1.FUNCTION_NAMESPACE: namespace, - }, + selector := map[string]string{ + v1.FUNCTION_NAME: input.String(flagkey.FnName), + } + if len(namespace) != 0 { + selector[v1.FUNCTION_NAMESPACE] = namespace } - pods, err := opts.Client().V1().Function().ListPods(m) + pods, err := opts.Client().KubernetesClient.CoreV1().Pods(metav1.NamespaceAll).List(input.Context(), metav1.ListOptions{ + LabelSelector: labels.Set(selector).AsSelector().String(), + }) if err != nil { return errors.Wrap(err, "error listing environments") } w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t\n", "NAME", "NAMESPACE", "READY", "STATUS", "IP", "EXECUTORTYPE", "MANAGED") - for _, pod := range pods { + for _, pod := range pods.Items { // A deletion timestamp indicates that a pod is terminating. Do not count this pod. if pod.ObjectMeta.DeletionTimestamp != nil { diff --git a/pkg/fission-cli/cmd/function/run_container.go b/pkg/fission-cli/cmd/function/run_container.go index 492ac8db..d603e1ad 100644 --- a/pkg/fission-cli/cmd/function/run_container.go +++ b/pkg/fission-cli/cmd/function/run_container.go @@ -22,11 +22,10 @@ import ( "github.com/pkg/errors" apiv1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" + kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" - ferror "github.com/fission/fission/pkg/error" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd/spec" @@ -56,7 +55,7 @@ func (opts *RunContainerSubCommand) do(input cli.Input) error { func (opts *RunContainerSubCommand) complete(input cli.Input) error { fnName := input.String(flagkey.FnName) - _, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + _, fnNamespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in running container for function ") } @@ -70,13 +69,11 @@ func (opts *RunContainerSubCommand) complete(input cli.Input) error { if !toSpec { // check for unique function names within a namespace - fn, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ - Name: input.String(flagkey.FnName), - Namespace: fnNamespace, - }) - if err != nil && !ferror.IsNotFound(err) { + fn, err := opts.Client().FissionClientSet.CoreV1().Functions(fnNamespace).Get(input.Context(), input.String(flagkey.FnName), metav1.GetOptions{}) + + if err != nil && !kerrors.IsNotFound(err) { return err - } else if fn != nil { + } else if fn.Name != "" && fn.Namespace != "" { return errors.New("a function with the same name already exists") } } @@ -128,12 +125,9 @@ func (opts *RunContainerSubCommand) complete(input cli.Input) error { // check the referenced secret is in the same ns as the function, if not give a warning. if !toSpec { // TODO: workaround in order not to block users from creating function spec, remove it. for _, secretName := range secretNames { - err := opts.Client().V1().Misc().SecretExists(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: secretName, - }) + err := util.SecretExists(input.Context(), &metav1.ObjectMeta{Namespace: fnNamespace, Name: secretName}, opts.Client().KubernetesClient) if err != nil { - if k8serrors.IsNotFound(err) { + if kerrors.IsNotFound(err) { console.Warn(fmt.Sprintf("Secret %s not found in Namespace: %s. Secret needs to be present in the same namespace as function", secretName, fnNamespace)) } else { return errors.Wrapf(err, "error checking secret %s", secretName) @@ -154,12 +148,10 @@ func (opts *RunContainerSubCommand) complete(input cli.Input) error { // check the referenced cfgmap is in the same ns as the function, if not give a warning. if !toSpec { for _, cfgMapName := range cfgMapNames { - err := opts.Client().V1().Misc().ConfigMapExists(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: cfgMapName, - }) + err := util.ConfigMapExists(input.Context(), &metav1.ObjectMeta{Namespace: fnNamespace, Name: cfgMapName}, opts.Client().KubernetesClient) + if err != nil { - if k8serrors.IsNotFound(err) { + if kerrors.IsNotFound(err) { console.Warn(fmt.Sprintf("ConfigMap %s not found in Namespace: %s. ConfigMap needs to be present in the same namespace as function", cfgMapName, fnNamespace)) } else { return errors.Wrapf(err, "error checking configmap %s", cfgMapName) @@ -238,7 +230,7 @@ func (opts *RunContainerSubCommand) run(input cli.Input) error { return nil } - _, err := opts.Client().V1().Function().Create(opts.function) + _, err := opts.Client().FissionClientSet.CoreV1().Functions(opts.function.ObjectMeta.Namespace).Create(input.Context(), opts.function, metav1.CreateOptions{}) if err != nil { return errors.Wrap(err, "error creating function") } diff --git a/pkg/fission-cli/cmd/function/test.go b/pkg/fission-cli/cmd/function/test.go index 5582d2c6..8768afc5 100644 --- a/pkg/fission-cli/cmd/function/test.go +++ b/pkg/fission-cli/cmd/function/test.go @@ -32,7 +32,6 @@ import ( "go.opentelemetry.io/otel" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd/httptrigger" @@ -52,7 +51,7 @@ func Test(input cli.Input) error { func (opts *TestSubCommand) do(input cli.Input) error { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in testing function ") } @@ -61,14 +60,13 @@ func (opts *TestSubCommand) do(input cli.Input) error { Name: input.String(flagkey.FnName), Namespace: namespace, } - kubeContext := input.String(flagkey.KubeContext) routerURL := os.Getenv("FISSION_ROUTER") if len(routerURL) != 0 { console.Warn("The environment variable FISSION_ROUTER is no longer supported for this command") } // Portforward to the fission router - localRouterPort, err := util.SetupPortForward(input.Context(), util.GetFissionNamespace(), "application=fission-router", kubeContext) + localRouterPort, err := util.SetupPortForward(input.Context(), opts.Client(), util.GetFissionNamespace(), "application=fission-router") if err != nil { return err } @@ -150,15 +148,13 @@ func (opts *TestSubCommand) do(input cli.Input) error { } console.Errorf("Error calling function %s: %d; Please try again or fix the error: %s\n", m.Name, resp.StatusCode, string(body)) - log, err := printPodLogs(opts.Client(), m) + err = printPodLogs(input.Context(), opts.Client(), m) if err != nil { console.Errorf("Error getting function logs from controller: %v. Try to get logs from log database.", err) err = Log(input) if err != nil { return errors.Wrapf(err, "error retrieving function log from log database") } - } else { - console.Info(log) } return errors.New("error getting function response") } @@ -224,21 +220,12 @@ func doHTTPRequest(ctx context.Context, url string, headers []string, method, bo return resp, nil } -func printPodLogs(client client.Interface, fnMeta *metav1.ObjectMeta) (string, error) { - reader, statusCode, err := client.V1().Misc().PodLogs(fnMeta) +func printPodLogs(ctx context.Context, client cmd.Client, fnMeta *metav1.ObjectMeta) error { + err := util.FunctionPodLogs(ctx, fnMeta.Name, fnMeta.Namespace, client) + if err != nil { - return "", errors.Wrap(err, "error executing get logs request") - } - defer reader.Close() - - body, err := io.ReadAll(reader) - if err != nil { - return "", errors.Wrap(err, "error reading the response body") + return errors.Wrap(err, "error executing get logs request") } - if statusCode != http.StatusOK { - return string(body), errors.Errorf("error getting logs from controller, status code: '%v'", statusCode) - } - - return string(body), nil + return nil } diff --git a/pkg/fission-cli/cmd/function/update.go b/pkg/fission-cli/cmd/function/update.go index 42c22c9d..e39aefce 100644 --- a/pkg/fission-cli/cmd/function/update.go +++ b/pkg/fission-cli/cmd/function/update.go @@ -51,15 +51,12 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { func (opts *UpdateSubCommand) complete(input cli.Input) error { fnName := input.String(flagkey.FnName) - _, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + _, fnNamespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in updating function ") } - function, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ - Name: input.String(flagkey.FnName), - Namespace: fnNamespace, - }) + function, err := opts.Client().FissionClientSet.CoreV1().Functions(fnNamespace).Get(input.Context(), input.String(flagkey.FnName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, fmt.Sprintf("read function '%v'", fnName)) } @@ -90,10 +87,7 @@ func (opts *UpdateSubCommand) complete(input cli.Input) error { // check that the referenced secret is in the same ns as the function, if not give a warning. for _, secretName := range secretNames { - err := opts.Client().V1().Misc().SecretExists(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: secretName, - }) + err := util.SecretExists(input.Context(), &metav1.ObjectMeta{Namespace: fnNamespace, Name: secretName}, opts.Client().KubernetesClient) if k8serrors.IsNotFound(err) { console.Warn(fmt.Sprintf("secret %s not found in Namespace: %s. Secret needs to be present in the same namespace as function", secretName, fnNamespace)) } @@ -114,10 +108,7 @@ func (opts *UpdateSubCommand) complete(input cli.Input) error { // check that the referenced cfgmap is in the same ns as the function, if not give a warning. for _, cfgMapName := range cfgMapNames { - err := opts.Client().V1().Misc().ConfigMapExists(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: cfgMapName, - }) + err := util.ConfigMapExists(input.Context(), &metav1.ObjectMeta{Namespace: fnNamespace, Name: cfgMapName}, opts.Client().KubernetesClient) if k8serrors.IsNotFound(err) { console.Warn(fmt.Sprintf("ConfigMap %s not found in Namespace: %s. ConfigMap needs to be present in the same namespace as the function", cfgMapName, fnNamespace)) } @@ -186,17 +177,14 @@ func (opts *UpdateSubCommand) complete(input cli.Input) error { function.Spec.Resources = *resReqs - pkg, err := opts.Client().V1().Package().Get(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: pkgName, - }) + pkg, err := opts.Client().FissionClientSet.CoreV1().Packages(fnNamespace).Get(input.Context(), pkgName, metav1.GetOptions{}) if err != nil { return errors.Wrap(err, fmt.Sprintf("read package '%v.%v'. Pkg should be present in the same ns as the function", pkgName, fnNamespace)) } forceUpdate := input.Bool(flagkey.PkgForce) - fnList, err := _package.GetFunctionsByPackage(opts.Client(), pkg.ObjectMeta.Name, pkg.ObjectMeta.Namespace) + fnList, err := _package.GetFunctionsByPackage(input.Context(), opts.Client(), pkg.ObjectMeta.Name, pkg.ObjectMeta.Namespace) if err != nil { return errors.Wrap(err, "error getting function list") } @@ -222,7 +210,7 @@ func (opts *UpdateSubCommand) complete(input cli.Input) error { fns = append(fns, fn) } } - err = _package.UpdateFunctionPackageResourceVersion(opts.Client(), newPkgMeta, fns...) + err = _package.UpdateFunctionPackageResourceVersion(input.Context(), opts.Client(), newPkgMeta, fns...) if err != nil { return errors.Wrap(err, "error updating function package reference resource version") } @@ -255,7 +243,7 @@ func (opts *UpdateSubCommand) complete(input cli.Input) error { } func (opts *UpdateSubCommand) run(input cli.Input) error { - _, err := opts.Client().V1().Function().Update(opts.function) + _, err := opts.Client().FissionClientSet.CoreV1().Functions(opts.function.Namespace).Update(input.Context(), opts.function, metav1.UpdateOptions{}) if err != nil { return errors.Wrap(err, "error updating function") } diff --git a/pkg/fission-cli/cmd/function/update_container.go b/pkg/fission-cli/cmd/function/update_container.go index 13633ca3..9b34db1e 100644 --- a/pkg/fission-cli/cmd/function/update_container.go +++ b/pkg/fission-cli/cmd/function/update_container.go @@ -53,15 +53,13 @@ func (opts *UpdateContainerSubCommand) do(input cli.Input) error { func (opts *UpdateContainerSubCommand) complete(input cli.Input) error { fnName := input.String(flagkey.FnName) - _, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + _, fnNamespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in updating container for function ") } - function, err := opts.Client().V1().Function().Get(&metav1.ObjectMeta{ - Name: input.String(flagkey.FnName), - Namespace: fnNamespace, - }) + function, err := opts.Client().FissionClientSet.CoreV1().Functions(fnNamespace).Get(input.Context(), input.String(flagkey.FnName), metav1.GetOptions{}) + if err != nil { return errors.Wrap(err, fmt.Sprintf("read function '%v'", fnName)) } @@ -84,10 +82,7 @@ func (opts *UpdateContainerSubCommand) complete(input cli.Input) error { // check that the referenced secret is in the same ns as the function, if not give a warning. for _, secretName := range secretNames { - err := opts.Client().V1().Misc().SecretExists(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: secretName, - }) + err := util.SecretExists(input.Context(), &metav1.ObjectMeta{Namespace: fnNamespace, Name: secretName}, opts.Client().KubernetesClient) if k8serrors.IsNotFound(err) { console.Warn(fmt.Sprintf("secret %s not found in Namespace: %s. Secret needs to be present in the same namespace as function", secretName, fnNamespace)) } @@ -108,10 +103,7 @@ func (opts *UpdateContainerSubCommand) complete(input cli.Input) error { // check that the referenced cfgmap is in the same ns as the function, if not give a warning. for _, cfgMapName := range cfgMapNames { - err := opts.Client().V1().Misc().ConfigMapExists(&metav1.ObjectMeta{ - Namespace: fnNamespace, - Name: cfgMapName, - }) + err := util.ConfigMapExists(input.Context(), &metav1.ObjectMeta{Namespace: fnNamespace, Name: cfgMapName}, opts.Client().KubernetesClient) if k8serrors.IsNotFound(err) { console.Warn(fmt.Sprintf("ConfigMap %s not found in Namespace: %s. ConfigMap needs to be present in the same namespace as the function", cfgMapName, fnNamespace)) } @@ -192,7 +184,7 @@ func (opts *UpdateContainerSubCommand) complete(input cli.Input) error { } func (opts *UpdateContainerSubCommand) run(input cli.Input) error { - _, err := opts.Client().V1().Function().Update(opts.function) + _, err := opts.Client().FissionClientSet.CoreV1().Functions(opts.function.Namespace).Update(input.Context(), opts.function, metav1.UpdateOptions{}) if err != nil { return errors.Wrap(err, "error updating function") } diff --git a/pkg/fission-cli/cmd/httptrigger/create.go b/pkg/fission-cli/cmd/httptrigger/create.go index 77e42935..235d8899 100644 --- a/pkg/fission-cli/cmd/httptrigger/create.go +++ b/pkg/fission-cli/cmd/httptrigger/create.go @@ -24,10 +24,10 @@ import ( "github.com/pkg/errors" uuid "github.com/satori/go.uuid" + kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" - ferror "github.com/fission/fission/pkg/error" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd/spec" @@ -77,7 +77,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { triggerName = id.String() } - userProvidedNS, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + userProvidedNS, fnNamespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in deleting function ") } @@ -129,11 +129,11 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { // For Specs, the spec validate checks for function reference if input.Bool(flagkey.SpecSave) { - htTrigger, err := opts.Client().V1().HTTPTrigger().Get(&m) - if err != nil && !ferror.IsNotFound(err) { + htTrigger, err := opts.Client().FissionClientSet.CoreV1().HTTPTriggers(m.Namespace).Get(input.Context(), m.Name, metav1.GetOptions{}) + if err != nil && !kerrors.IsNotFound(err) { return err } - if htTrigger != nil { + if htTrigger.Name != "" && htTrigger.Namespace != "" { return errors.New("duplicate trigger exists, choose a different name or leave it empty for fission to auto-generate it") } @@ -164,16 +164,16 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { Name: triggerName, Namespace: fnNamespace, } + htTrigger, err := opts.Client().FissionClientSet.CoreV1().HTTPTriggers(m.Namespace).Get(input.Context(), m.Name, metav1.GetOptions{}) - htTrigger, err := opts.Client().V1().HTTPTrigger().Get(&m) - if err != nil && !ferror.IsNotFound(err) { + if err != nil && !kerrors.IsNotFound(err) { return err } - if htTrigger != nil { + if htTrigger != nil && htTrigger.Namespace != "" { return errors.New("duplicate trigger exists, choose a different name or leave it empty for fission to auto-generate it") } - err = util.CheckFunctionExistence(opts.Client(), functionList, fnNamespace) + err = util.CheckFunctionExistence(input.Context(), opts.Client(), functionList, fnNamespace) if err != nil { console.Warn(err.Error()) } @@ -226,7 +226,13 @@ func (opts *CreateSubCommand) run(input cli.Input) error { return nil } - _, err := opts.Client().V1().HTTPTrigger().Create(opts.trigger) + // Ensure we don't have a duplicate HTTP route defined (same URL and method) + err := util.CheckHTTPTriggerDuplicates(input.Context(), opts.Client(), opts.trigger) + if err != nil { + return errors.Wrap(err, "Error while creating HTTP Trigger") + } + + _, err = opts.Client().FissionClientSet.CoreV1().HTTPTriggers(opts.trigger.Namespace).Create(input.Context(), opts.trigger, metav1.CreateOptions{}) if err != nil { return errors.Wrap(err, "create HTTP trigger") } diff --git a/pkg/fission-cli/cmd/httptrigger/delete.go b/pkg/fission-cli/cmd/httptrigger/delete.go index 3f35b9bb..5f578923 100644 --- a/pkg/fission-cli/cmd/httptrigger/delete.go +++ b/pkg/fission-cli/cmd/httptrigger/delete.go @@ -58,7 +58,7 @@ func (opts *DeleteSubCommand) complete(input cli.Input) (err error) { return errors.Errorf("need either of --%v or --%v and not both arguments", flagkey.HtName, flagkey.HtFnName) } - _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + _, opts.namespace, err = opts.GetResourceNamespace(input, flagkey.NamespaceTrigger) if err != nil { return errors.Wrap(err, "error in deleting function ") } @@ -66,7 +66,7 @@ func (opts *DeleteSubCommand) complete(input cli.Input) (err error) { } func (opts *DeleteSubCommand) run(input cli.Input) error { - triggers, err := opts.Client().V1().HTTPTrigger().List(opts.namespace) + triggers, err := opts.Client().FissionClientSet.CoreV1().HTTPTriggers(opts.namespace).List(input.Context(), metav1.ListOptions{}) if err != nil { return errors.Wrap(err, "error getting HTTP trigger list") } @@ -74,7 +74,7 @@ func (opts *DeleteSubCommand) run(input cli.Input) error { var triggersToDelete []string if len(opts.functionName) > 0 { - for _, trigger := range triggers { + for _, trigger := range triggers.Items { // TODO: delete canary http triggers as well. if trigger.Spec.FunctionReference.Name == opts.functionName { triggersToDelete = append(triggersToDelete, trigger.ObjectMeta.Name) @@ -87,10 +87,7 @@ func (opts *DeleteSubCommand) run(input cli.Input) error { errs := utils.MultiErrorWithFormat() for _, name := range triggersToDelete { - err := opts.Client().V1().HTTPTrigger().Delete(&metav1.ObjectMeta{ - Name: name, - Namespace: opts.namespace, - }) + err := opts.Client().FissionClientSet.CoreV1().HTTPTriggers(opts.namespace).Delete(input.Context(), name, metav1.DeleteOptions{}) if err != nil { errs = multierror.Append(errs, err) } else { diff --git a/pkg/fission-cli/cmd/httptrigger/get.go b/pkg/fission-cli/cmd/httptrigger/get.go index 77fb4511..c7f56e97 100644 --- a/pkg/fission-cli/cmd/httptrigger/get.go +++ b/pkg/fission-cli/cmd/httptrigger/get.go @@ -29,7 +29,6 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type GetSubCommand struct { @@ -45,16 +44,12 @@ func (opts *GetSubCommand) do(input cli.Input) error { } func (opts *GetSubCommand) run(input cli.Input) (err error) { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in deleting function ") } - m := &metav1.ObjectMeta{ - Name: input.String(flagkey.HtName), - Namespace: namespace, - } - ht, err := opts.Client().V1().HTTPTrigger().Get(m) + ht, err := opts.Client().FissionClientSet.CoreV1().HTTPTriggers(namespace).Get(input.Context(), input.String(flagkey.HtName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting http trigger") } diff --git a/pkg/fission-cli/cmd/httptrigger/list.go b/pkg/fission-cli/cmd/httptrigger/list.go index cdbf9df9..de9b965a 100644 --- a/pkg/fission-cli/cmd/httptrigger/list.go +++ b/pkg/fission-cli/cmd/httptrigger/list.go @@ -18,12 +18,12 @@ package httptrigger import ( "github.com/pkg/errors" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -40,17 +40,15 @@ func (opts *ListSubCommand) do(input cli.Input) error { func (opts *ListSubCommand) run(input cli.Input) (err error) { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceTrigger) if err != nil { return errors.Wrap(err, "error in deleting function ") } - var hts []fv1.HTTPTrigger if input.Bool(flagkey.AllNamespaces) { - hts, err = opts.Client().V1().HTTPTrigger().List("") - } else { - hts, err = opts.Client().V1().HTTPTrigger().List(namespace) + namespace = v1.NamespaceAll } + hts, err := opts.Client().FissionClientSet.CoreV1().HTTPTriggers(namespace).List(input.Context(), v1.ListOptions{}) if err != nil { return errors.Wrap(err, "error listing HTTP triggers") @@ -59,7 +57,7 @@ func (opts *ListSubCommand) run(input cli.Input) (err error) { filterFunctionName := input.String(flagkey.HtFnName) var triggers []fv1.HTTPTrigger - for _, ht := range hts { + for _, ht := range hts.Items { // TODO: list canary http triggers as well. if len(filterFunctionName) == 0 || (len(filterFunctionName) > 0 && filterFunctionName == ht.Spec.FunctionReference.Name) { diff --git a/pkg/fission-cli/cmd/httptrigger/update.go b/pkg/fission-cli/cmd/httptrigger/update.go index 31010a93..b1357c79 100644 --- a/pkg/fission-cli/cmd/httptrigger/update.go +++ b/pkg/fission-cli/cmd/httptrigger/update.go @@ -51,15 +51,12 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { htName := input.String(flagkey.HtName) - _, triggerNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + _, triggerNamespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceTrigger) if err != nil { return errors.Wrap(err, "error in deleting function ") } - ht, err := opts.Client().V1().HTTPTrigger().Get(&metav1.ObjectMeta{ - Name: htName, - Namespace: triggerNamespace, - }) + ht, err := opts.Client().FissionClientSet.CoreV1().HTTPTriggers(triggerNamespace).Get(input.Context(), htName, metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting HTTP trigger") } @@ -102,7 +99,7 @@ func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { if input.IsSet(flagkey.HtFnName) { // get the functions and their weights if specified functionList := input.StringSlice(flagkey.HtFnName) - err := util.CheckFunctionExistence(opts.Client(), functionList, triggerNamespace) + err := util.CheckFunctionExistence(input.Context(), opts.Client(), functionList, triggerNamespace) if err != nil { console.Warn(err.Error()) } @@ -151,7 +148,13 @@ func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { } func (opts *UpdateSubCommand) run(input cli.Input) error { - _, err := opts.Client().V1().HTTPTrigger().Update(opts.trigger) + + err := util.CheckHTTPTriggerDuplicates(input.Context(), opts.Client(), opts.trigger) + if err != nil { + return errors.Wrap(err, "Error while creating HTTP Trigger") + } + + _, err = opts.Client().FissionClientSet.CoreV1().HTTPTriggers(opts.trigger.ObjectMeta.Namespace).Update(input.Context(), opts.trigger, metav1.UpdateOptions{}) if err != nil { return errors.Wrap(err, "error updating the HTTP trigger") } diff --git a/pkg/fission-cli/cmd/kubewatch/create.go b/pkg/fission-cli/cmd/kubewatch/create.go index 1c4ab2fa..0ba2c66a 100644 --- a/pkg/fission-cli/cmd/kubewatch/create.go +++ b/pkg/fission-cli/cmd/kubewatch/create.go @@ -61,7 +61,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { } fnName := input.String(flagkey.KwFnName) - _, namespace, err := util.GetResourceNamespace(input, flagkey.KwNamespace) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.KwNamespace) if err != nil { return errors.Wrap(err, "error in listing function ") } @@ -126,7 +126,7 @@ func (opts *CreateSubCommand) run(input cli.Input) error { return nil } - _, err := opts.Client().V1().KubeWatcher().Create(opts.watcher) + _, err := opts.Client().FissionClientSet.CoreV1().KubernetesWatchTriggers(opts.watcher.ObjectMeta.Namespace).Create(input.Context(), opts.watcher, metav1.CreateOptions{}) if err != nil { return errors.Wrap(err, "error creating kubewatch") } diff --git a/pkg/fission-cli/cmd/kubewatch/delete.go b/pkg/fission-cli/cmd/kubewatch/delete.go index ff351dd9..912b4a66 100644 --- a/pkg/fission-cli/cmd/kubewatch/delete.go +++ b/pkg/fission-cli/cmd/kubewatch/delete.go @@ -48,7 +48,7 @@ func (opts *DeleteSubCommand) do(input cli.Input) error { func (opts *DeleteSubCommand) complete(input cli.Input) (err error) { opts.name = input.String(flagkey.KwName) - _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + _, opts.namespace, err = opts.GetResourceNamespace(input, flagkey.NamespaceTrigger) if err != nil { return errors.Wrap(err, "error in deleting kubewatch") } @@ -56,10 +56,7 @@ func (opts *DeleteSubCommand) complete(input cli.Input) (err error) { } func (opts *DeleteSubCommand) run(input cli.Input) error { - err := opts.Client().V1().KubeWatcher().Delete(&metav1.ObjectMeta{ - Name: opts.name, - Namespace: opts.namespace, - }) + err := opts.Client().FissionClientSet.CoreV1().KubernetesWatchTriggers(opts.namespace).Delete(input.Context(), opts.name, metav1.DeleteOptions{}) if err != nil { if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { return nil diff --git a/pkg/fission-cli/cmd/kubewatch/list.go b/pkg/fission-cli/cmd/kubewatch/list.go index 05531b51..a0e9d19d 100644 --- a/pkg/fission-cli/cmd/kubewatch/list.go +++ b/pkg/fission-cli/cmd/kubewatch/list.go @@ -22,12 +22,12 @@ import ( "text/tabwriter" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -48,7 +48,7 @@ func (opts *ListSubCommand) do(input cli.Input) error { } func (opts *ListSubCommand) complete(input cli.Input) (err error) { - _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + _, opts.namespace, err = opts.GetResourceNamespace(input, flagkey.NamespaceTrigger) if err != nil { return errors.Wrap(err, "error listing kubewatchers") } @@ -56,12 +56,12 @@ func (opts *ListSubCommand) complete(input cli.Input) (err error) { } func (opts *ListSubCommand) run(input cli.Input) (err error) { - var ws []v1.KubernetesWatchTrigger + var ws *v1.KubernetesWatchTriggerList if input.Bool(flagkey.AllNamespaces) { - ws, err = opts.Client().V1().KubeWatcher().List("") - } else { - ws, err = opts.Client().V1().KubeWatcher().List(opts.namespace) + opts.namespace = metav1.NamespaceAll } + ws, err = opts.Client().FissionClientSet.CoreV1().KubernetesWatchTriggers(opts.namespace).List(input.Context(), metav1.ListOptions{}) + if err != nil { return errors.Wrap(err, "error listing kubewatchers") } @@ -70,7 +70,7 @@ func (opts *ListSubCommand) run(input cli.Input) (err error) { fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\n", "NAME", "NAMESPACE", "OBJTYPE", "LABELS", "FUNCTION_NAME") - for _, wa := range ws { + for _, wa := range ws.Items { fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\n", wa.ObjectMeta.Name, wa.Spec.Namespace, wa.Spec.Type, wa.Spec.LabelSelector, wa.Spec.FunctionReference.Name) } diff --git a/pkg/fission-cli/cmd/mqtrigger/create.go b/pkg/fission-cli/cmd/mqtrigger/create.go index ef614050..893fe870 100644 --- a/pkg/fission-cli/cmd/mqtrigger/create.go +++ b/pkg/fission-cli/cmd/mqtrigger/create.go @@ -62,7 +62,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { } fnName := input.String(flagkey.MqtFnName) - userProvidedNS, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + userProvidedNS, fnNamespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in deleting function ") } @@ -151,7 +151,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { mqtName, fnName)) } } else { - err = util.CheckFunctionExistence(opts.Client(), []string{fnName}, fnNamespace) + err = util.CheckFunctionExistence(input.Context(), opts.Client(), []string{fnName}, fnNamespace) if err != nil { return err } @@ -210,7 +210,7 @@ func (opts *CreateSubCommand) run(input cli.Input) error { return nil } - _, err := opts.Client().V1().MessageQueueTrigger().Create(opts.trigger) + _, err := opts.Client().FissionClientSet.CoreV1().MessageQueueTriggers(opts.trigger.ObjectMeta.Namespace).Create(input.Context(), opts.trigger, metav1.CreateOptions{}) if err != nil { return errors.Wrap(err, "create message queue trigger") } diff --git a/pkg/fission-cli/cmd/mqtrigger/delete.go b/pkg/fission-cli/cmd/mqtrigger/delete.go index a0ed824b..3302357c 100644 --- a/pkg/fission-cli/cmd/mqtrigger/delete.go +++ b/pkg/fission-cli/cmd/mqtrigger/delete.go @@ -20,12 +20,12 @@ import ( "fmt" "github.com/pkg/errors" + kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type DeleteSubCommand struct { @@ -47,7 +47,7 @@ func (opts *DeleteSubCommand) do(input cli.Input) error { func (opts *DeleteSubCommand) complete(input cli.Input) (err error) { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceTrigger) if err != nil { return errors.Wrap(err, "error in deleting function ") } @@ -60,9 +60,9 @@ func (opts *DeleteSubCommand) complete(input cli.Input) (err error) { } func (opts *DeleteSubCommand) run(input cli.Input) error { - err := opts.Client().V1().MessageQueueTrigger().Delete(opts.metadata) + err := opts.Client().FissionClientSet.CoreV1().MessageQueueTriggers(opts.metadata.Namespace).Delete(input.Context(), opts.metadata.Name, metav1.DeleteOptions{}) if err != nil { - if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { + if input.Bool(flagkey.IgnoreNotFound) && kerrors.IsNotFound(err) { return nil } return errors.Wrap(err, "error deleting message queue trigger") diff --git a/pkg/fission-cli/cmd/mqtrigger/list.go b/pkg/fission-cli/cmd/mqtrigger/list.go index e0b3e953..0e30339e 100644 --- a/pkg/fission-cli/cmd/mqtrigger/list.go +++ b/pkg/fission-cli/cmd/mqtrigger/list.go @@ -22,12 +22,11 @@ import ( "text/tabwriter" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -48,7 +47,7 @@ func (opts *ListSubCommand) do(input cli.Input) error { } func (opts *ListSubCommand) complete(input cli.Input) (err error) { - _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + _, opts.namespace, err = opts.GetResourceNamespace(input, flagkey.NamespaceTrigger) if err != nil { return errors.Wrap(err, "error in deleting function ") } @@ -57,12 +56,11 @@ func (opts *ListSubCommand) complete(input cli.Input) (err error) { func (opts *ListSubCommand) run(input cli.Input) (err error) { - var mqts []v1.MessageQueueTrigger if input.Bool(flagkey.AllNamespaces) { - mqts, err = opts.Client().V1().MessageQueueTrigger().List(input.String(flagkey.MqtMQType), "") - } else { - mqts, err = opts.Client().V1().MessageQueueTrigger().List(input.String(flagkey.MqtMQType), opts.namespace) + opts.namespace = metav1.NamespaceAll } + mqts, err := opts.Client().FissionClientSet.CoreV1().MessageQueueTriggers(opts.namespace).List(input.Context(), metav1.ListOptions{}) + if err != nil { return errors.Wrap(err, "error listing message queue triggers") } @@ -71,7 +69,7 @@ func (opts *ListSubCommand) run(input cli.Input) (err error) { fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", "NAME", "FUNCTION_NAME", "MESSAGE_QUEUE_TYPE", "TOPIC", "RESPONSE_TOPIC", "ERROR_TOPIC", "MAX_RETRIES", "PUB_MSG_CONTENT_TYPE", "NAMESPACE") - for _, mqt := range mqts { + for _, mqt := range mqts.Items { fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", mqt.ObjectMeta.Name, mqt.Spec.FunctionReference.Name, mqt.Spec.MessageQueueType, mqt.Spec.Topic, mqt.Spec.ResponseTopic, mqt.Spec.ErrorTopic, mqt.Spec.MaxRetries, mqt.Spec.ContentType, mqt.ObjectMeta.Namespace) } diff --git a/pkg/fission-cli/cmd/mqtrigger/update.go b/pkg/fission-cli/cmd/mqtrigger/update.go index 5e88e81b..7c716041 100644 --- a/pkg/fission-cli/cmd/mqtrigger/update.go +++ b/pkg/fission-cli/cmd/mqtrigger/update.go @@ -48,15 +48,12 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { } func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceTrigger) if err != nil { return errors.Wrap(err, "error in deleting function ") } - mqt, err := opts.Client().V1().MessageQueueTrigger().Get(&metav1.ObjectMeta{ - Name: input.String(flagkey.MqtName), - Namespace: namespace, - }) + mqt, err := opts.Client().FissionClientSet.CoreV1().MessageQueueTriggers(namespace).Get(input.Context(), input.String(flagkey.MqtName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting message queue trigger") } @@ -100,7 +97,7 @@ func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { } if len(fnName) > 0 { functionList := []string{fnName} - err := util.CheckFunctionExistence(opts.Client(), functionList, namespace) + err := util.CheckFunctionExistence(input.Context(), opts.Client(), functionList, namespace) if err != nil { console.Warn(err.Error()) } @@ -151,7 +148,7 @@ func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { } func (opts *UpdateSubCommand) run(input cli.Input) error { - _, err := opts.Client().V1().MessageQueueTrigger().Update(opts.trigger) + _, err := opts.Client().FissionClientSet.CoreV1().MessageQueueTriggers(opts.trigger.ObjectMeta.Namespace).Update(input.Context(), opts.trigger, metav1.UpdateOptions{}) if err != nil { return errors.Wrap(err, "error updating message queue trigger") } diff --git a/pkg/fission-cli/cmd/package/create.go b/pkg/fission-cli/cmd/package/create.go index 6f811cb9..23923a32 100644 --- a/pkg/fission-cli/cmd/package/create.go +++ b/pkg/fission-cli/cmd/package/create.go @@ -28,7 +28,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" - "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd/spec" @@ -65,7 +64,7 @@ func (opts *CreateSubCommand) run(input cli.Input) error { envName := input.String(flagkey.PkgEnvironment) - userProvidedNS, pkgNamespace, err := util.GetResourceNamespace(input, flagkey.NamespacePackage) + userProvidedNS, pkgNamespace, err := opts.GetResourceNamespace(input, flagkey.NamespacePackage) if err != nil { return fv1.AggregateValidationErrors("Environment", err) } @@ -126,7 +125,7 @@ func (opts *CreateSubCommand) run(input cli.Input) error { } // TODO: get all necessary value from CLI input directly -func CreatePackage(input cli.Input, client client.Interface, pkgName string, pkgNamespace string, envName string, +func CreatePackage(input cli.Input, client cmd.Client, pkgName string, pkgNamespace string, envName string, srcArchiveFiles []string, deployArchiveFiles []string, buildcmd string, specDir string, specFile string, noZip bool, userProvidedNS string) (*metav1.ObjectMeta, error) { insecure := input.Bool(flagkey.PkgInsecure) @@ -224,11 +223,12 @@ func CreatePackage(input cli.Input, client client.Interface, pkgName string, pkg return &pkg.ObjectMeta, nil } else { pkg.ObjectMeta.Namespace = pkgNamespace - pkgMetadata, err := client.V1().Package().Create(pkg) + + pkgMetadata, err := client.FissionClientSet.CoreV1().Packages(pkgNamespace).Create(input.Context(), pkg, metav1.CreateOptions{}) if err != nil { return nil, errors.Wrap(err, "error creating package") } fmt.Printf("Package '%v' created\n", pkgMetadata.GetName()) - return pkgMetadata, nil + return &pkgMetadata.ObjectMeta, nil } } diff --git a/pkg/fission-cli/cmd/package/delete.go b/pkg/fission-cli/cmd/package/delete.go index 64f7fa69..a6e1d5da 100644 --- a/pkg/fission-cli/cmd/package/delete.go +++ b/pkg/fission-cli/cmd/package/delete.go @@ -17,17 +17,17 @@ limitations under the License. package _package import ( + "context" "fmt" "github.com/pkg/errors" + kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" - "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type DeleteSubCommand struct { @@ -52,7 +52,7 @@ func (opts *DeleteSubCommand) do(input cli.Input) error { func (opts *DeleteSubCommand) complete(input cli.Input) (err error) { opts.name = input.String(flagkey.PkgName) - _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespacePackage) + _, opts.namespace, err = opts.GetResourceNamespace(input, flagkey.NamespacePackage) if err != nil { return fv1.AggregateValidationErrors("Environment", err) } @@ -69,18 +69,15 @@ func (opts *DeleteSubCommand) complete(input cli.Input) (err error) { func (opts *DeleteSubCommand) run(input cli.Input) error { if len(opts.name) != 0 { - _, err := opts.Client().V1().Package().Get(&metav1.ObjectMeta{ - Namespace: opts.namespace, - Name: opts.name, - }) + _, err := opts.Client().FissionClientSet.CoreV1().Packages(opts.namespace).Get(input.Context(), opts.name, metav1.GetOptions{}) if err != nil { - if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { + if input.Bool(flagkey.IgnoreNotFound) && kerrors.IsNotFound(err) { return nil } return errors.Wrap(err, "find package") } - fnList, err := GetFunctionsByPackage(opts.Client(), opts.name, opts.namespace) + fnList, err := GetFunctionsByPackage(input.Context(), opts.Client(), opts.name, opts.namespace) if err != nil { return err } @@ -88,7 +85,7 @@ func (opts *DeleteSubCommand) run(input cli.Input) error { if !opts.force && len(fnList) > 0 { return errors.New("Package is used by at least one function, use -f to force delete") } - err = deletePackage(opts.Client(), opts.name, opts.namespace) + err = deletePackage(input.Context(), opts.Client(), opts.name, opts.namespace) if err != nil { return err } @@ -97,7 +94,7 @@ func (opts *DeleteSubCommand) run(input cli.Input) error { // TODO improve list speed when --orphan if opts.deleteOrphans { - err := deleteOrphanPkgs(opts.Client(), opts.namespace) + err := deleteOrphanPkgs(input.Context(), opts.Client(), opts.namespace) if err != nil { return errors.Wrap(err, "deleting orphan packages") } @@ -107,20 +104,20 @@ func (opts *DeleteSubCommand) run(input cli.Input) error { return nil } -func deleteOrphanPkgs(client client.Interface, pkgNamespace string) error { - pkgList, err := client.V1().Package().List(pkgNamespace) +func deleteOrphanPkgs(ctx context.Context, client cmd.Client, pkgNamespace string) error { + pkgList, err := client.FissionClientSet.CoreV1().Packages(pkgNamespace).List(ctx, metav1.ListOptions{}) if err != nil { return err } // range through all packages and find out the ones not referenced by any function - for _, pkg := range pkgList { - fnList, err := GetFunctionsByPackage(client, pkg.ObjectMeta.Name, pkgNamespace) + for _, pkg := range pkgList.Items { + fnList, err := GetFunctionsByPackage(ctx, client, pkg.ObjectMeta.Name, pkgNamespace) if err != nil { return errors.Wrap(err, fmt.Sprintf("get functions sharing package %s", pkg.ObjectMeta.Name)) } if len(fnList) == 0 { - err = deletePackage(client, pkg.ObjectMeta.Name, pkgNamespace) + err = deletePackage(ctx, client, pkg.ObjectMeta.Name, pkgNamespace) if err != nil { return err } @@ -129,9 +126,6 @@ func deleteOrphanPkgs(client client.Interface, pkgNamespace string) error { return nil } -func deletePackage(client client.Interface, pkgName string, pkgNamespace string) error { - return client.V1().Package().Delete(&metav1.ObjectMeta{ - Namespace: pkgNamespace, - Name: pkgName, - }) +func deletePackage(ctx context.Context, client cmd.Client, pkgName string, pkgNamespace string) error { + return client.FissionClientSet.CoreV1().Packages(pkgNamespace).Delete(ctx, pkgName, metav1.DeleteOptions{}) } diff --git a/pkg/fission-cli/cmd/package/get.go b/pkg/fission-cli/cmd/package/get.go index 0f170b07..37c0a2a0 100644 --- a/pkg/fission-cli/cmd/package/get.go +++ b/pkg/fission-cli/cmd/package/get.go @@ -21,6 +21,7 @@ import ( "io" "os" + "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" @@ -28,7 +29,6 @@ import ( "github.com/fission/fission/pkg/fission-cli/cmd" pkgutil "github.com/fission/fission/pkg/fission-cli/cmd/package/util" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) const ( @@ -61,7 +61,7 @@ func (opts *GetSubCommand) do(input cli.Input) error { func (opts *GetSubCommand) complete(input cli.Input) (err error) { opts.name = input.String(flagkey.PkgName) - _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespacePackage) + _, opts.namespace, err = opts.GetResourceNamespace(input, flagkey.NamespacePackage) if err != nil { return fv1.AggregateValidationErrors("Environment", err) } @@ -70,10 +70,8 @@ func (opts *GetSubCommand) complete(input cli.Input) (err error) { } func (opts *GetSubCommand) run(input cli.Input) error { - pkg, err := opts.Client().V1().Package().Get(&metav1.ObjectMeta{ - Namespace: opts.namespace, - Name: opts.name, - }) + + pkg, err := opts.Client().FissionClientSet.CoreV1().Packages(opts.namespace).Get(input.Context(), opts.name, metav1.GetOptions{}) if err != nil { return err } @@ -87,10 +85,12 @@ func (opts *GetSubCommand) run(input cli.Input) error { if pkg.Spec.Deployment.Type == fv1.ArchiveTypeLiteral { reader = bytes.NewReader(archive.Literal) } else if pkg.Spec.Deployment.Type == fv1.ArchiveTypeUrl { - readCloser, err := pkgutil.DownloadStoragesvcURL(opts.Client(), archive.URL) + + readCloser, err := pkgutil.DownloadStrorageURL(input.Context(), opts.Client(), archive.URL) if err != nil { - return err + return errors.Wrapf(err, "error downloading from storage service url: %s", archive.URL) } + defer readCloser.Close() reader = readCloser } diff --git a/pkg/fission-cli/cmd/package/info.go b/pkg/fission-cli/cmd/package/info.go index 3e3258ce..f4f06f7c 100644 --- a/pkg/fission-cli/cmd/package/info.go +++ b/pkg/fission-cli/cmd/package/info.go @@ -27,7 +27,6 @@ import ( "github.com/fission/fission/pkg/fission-cli/cmd" pkgutil "github.com/fission/fission/pkg/fission-cli/cmd/package/util" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type InfoSubCommand struct { @@ -51,7 +50,7 @@ func (opts *InfoSubCommand) do(input cli.Input) error { func (opts *InfoSubCommand) complete(input cli.Input) (err error) { opts.name = input.String(flagkey.PkgName) - _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespacePackage) + _, opts.namespace, err = opts.GetResourceNamespace(input, flagkey.NamespacePackage) if err != nil { return fv1.AggregateValidationErrors("Environment", err) } @@ -59,10 +58,11 @@ func (opts *InfoSubCommand) complete(input cli.Input) (err error) { } func (opts *InfoSubCommand) run(input cli.Input) error { - pkg, err := opts.Client().V1().Package().Get(&metav1.ObjectMeta{ - Namespace: opts.namespace, - Name: opts.name, - }) + pkg, err := opts.Client().FissionClientSet.CoreV1().Packages(opts.namespace).Get(input.Context(), opts.name, metav1.GetOptions{}) + if err != nil { + return err + } + if err != nil { return errors.Wrapf(err, "error finding package %s", opts.name) } diff --git a/pkg/fission-cli/cmd/package/list.go b/pkg/fission-cli/cmd/package/list.go index 21c01dcd..ac872c28 100644 --- a/pkg/fission-cli/cmd/package/list.go +++ b/pkg/fission-cli/cmd/package/list.go @@ -24,12 +24,12 @@ import ( "time" "github.com/pkg/errors" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -55,7 +55,7 @@ func (opts *ListSubCommand) complete(input cli.Input) (err error) { // option for the user to list all orphan packages (not referenced by any function) opts.listOrphans = input.Bool(flagkey.PkgOrphan) opts.status = input.String(flagkey.PkgStatus) - _, opts.pkgNamespace, err = util.GetResourceNamespace(input, flagkey.NamespacePackage) + _, opts.pkgNamespace, err = opts.GetResourceNamespace(input, flagkey.NamespacePackage) if err != nil { return fv1.AggregateValidationErrors("Environment", err) } @@ -64,29 +64,28 @@ func (opts *ListSubCommand) complete(input cli.Input) (err error) { func (opts *ListSubCommand) run(input cli.Input) (err error) { - var pkgList []fv1.Package if input.Bool(flagkey.AllNamespaces) { - pkgList, err = opts.Client().V1().Package().List("") - } else { - pkgList, err = opts.Client().V1().Package().List(opts.pkgNamespace) + opts.pkgNamespace = v1.NamespaceAll } + pkgList, err := opts.Client().FissionClientSet.CoreV1().Packages(opts.pkgNamespace).List(input.Context(), v1.ListOptions{}) + if err != nil { return err } // sort the package list by lastUpdatedTimestamp - sort.Slice(pkgList, func(i, j int) bool { - return pkgList[i].Status.LastUpdateTimestamp.After(pkgList[j].Status.LastUpdateTimestamp.Time) + sort.Slice(pkgList.Items, func(i, j int) bool { + return pkgList.Items[i].Status.LastUpdateTimestamp.After(pkgList.Items[j].Status.LastUpdateTimestamp.Time) }) w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\n", "NAME", "BUILD_STATUS", "ENV", "LASTUPDATEDAT", "NAMESPACE") - for _, pkg := range pkgList { + for _, pkg := range pkgList.Items { show := true // TODO improve list speed when --orphan if opts.listOrphans { - fnList, err := GetFunctionsByPackage(opts.Client(), pkg.ObjectMeta.Name, pkg.ObjectMeta.Namespace) + fnList, err := GetFunctionsByPackage(input.Context(), opts.Client(), pkg.ObjectMeta.Name, pkg.ObjectMeta.Namespace) if err != nil { return errors.Wrap(err, fmt.Sprintf("get functions sharing package %s", pkg.ObjectMeta.Name)) } diff --git a/pkg/fission-cli/cmd/package/package.go b/pkg/fission-cli/cmd/package/package.go index 83f2a1aa..5f1d7101 100644 --- a/pkg/fission-cli/cmd/package/package.go +++ b/pkg/fission-cli/cmd/package/package.go @@ -17,6 +17,7 @@ limitations under the License. package _package import ( + "context" "fmt" "net/http" "os" @@ -27,10 +28,11 @@ import ( "github.com/hashicorp/go-multierror" "github.com/pkg/errors" uuid "github.com/satori/go.uuid" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" - "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" + "github.com/fission/fission/pkg/fission-cli/cmd" pkgutil "github.com/fission/fission/pkg/fission-cli/cmd/package/util" "github.com/fission/fission/pkg/fission-cli/cmd/spec" spectypes "github.com/fission/fission/pkg/fission-cli/cmd/spec/types" @@ -44,7 +46,7 @@ import ( // create an archive upload spec in the specs directory; otherwise // upload the archive using client. noZip avoids zipping the // includeFiles, but is ignored if there's more than one includeFile. -func CreateArchive(client client.Interface, input cli.Input, includeFiles []string, noZip bool, insecure bool, checksum string, specDir string, specFile string) (*fv1.Archive, error) { +func CreateArchive(client cmd.Client, input cli.Input, includeFiles []string, noZip bool, insecure bool, checksum string, specDir string, specFile string) (*fv1.Archive, error) { // get root dir var rootDir string var err error @@ -251,13 +253,13 @@ func archiveName(givenNameHint string, includedFiles []string) string { return fmt.Sprintf("%v-%v", util.KubifyName(includedFiles[0]), uniuri.NewLen(4)) } -func GetFunctionsByPackage(client client.Interface, pkgName, pkgNamespace string) ([]fv1.Function, error) { - fnList, err := client.V1().Function().List(pkgNamespace) +func GetFunctionsByPackage(ctx context.Context, client cmd.Client, pkgName, pkgNamespace string) ([]fv1.Function, error) { + fnList, err := client.FissionClientSet.CoreV1().Functions(pkgNamespace).List(ctx, v1.ListOptions{}) if err != nil { return nil, err } fns := []fv1.Function{} - for _, fn := range fnList { + for _, fn := range fnList.Items { if fn.Spec.Package.PackageRef.Name == pkgName { fns = append(fns, fn) } diff --git a/pkg/fission-cli/cmd/package/rebuild.go b/pkg/fission-cli/cmd/package/rebuild.go index 0e9d61cb..4d4b6e54 100644 --- a/pkg/fission-cli/cmd/package/rebuild.go +++ b/pkg/fission-cli/cmd/package/rebuild.go @@ -26,7 +26,6 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type RebuildSubCommand struct { @@ -49,7 +48,7 @@ func (opts *RebuildSubCommand) do(input cli.Input) error { func (opts *RebuildSubCommand) complete(input cli.Input) (err error) { opts.name = input.String(flagkey.PkgName) - _, opts.namespace, err = util.GetResourceNamespace(input, flagkey.NamespacePackage) + _, opts.namespace, err = opts.GetResourceNamespace(input, flagkey.NamespacePackage) if err != nil { return fv1.AggregateValidationErrors("Environment", err) } @@ -57,10 +56,10 @@ func (opts *RebuildSubCommand) complete(input cli.Input) (err error) { } func (opts *RebuildSubCommand) run(input cli.Input) error { - pkg, err := opts.Client().V1().Package().Get(&metav1.ObjectMeta{ - Name: opts.name, - Namespace: opts.namespace, - }) + pkg, err := opts.Client().FissionClientSet.CoreV1().Packages(opts.namespace).Get(input.Context(), opts.name, metav1.GetOptions{}) + if err != nil { + return err + } if err != nil { return errors.Wrap(err, "find package") } @@ -70,7 +69,7 @@ func (opts *RebuildSubCommand) run(input cli.Input) error { pkg.ObjectMeta.Name, fv1.BuildStatusFailed)) } - _, err = updatePackageStatus(opts.Client(), pkg, fv1.BuildStatusPending) + _, err = updatePackageStatus(input.Context(), opts.Client(), pkg, fv1.BuildStatusPending) if err != nil { return errors.Wrap(err, "update package status") } diff --git a/pkg/fission-cli/cmd/package/update.go b/pkg/fission-cli/cmd/package/update.go index 7ff2da7e..faed8dae 100644 --- a/pkg/fission-cli/cmd/package/update.go +++ b/pkg/fission-cli/cmd/package/update.go @@ -17,6 +17,7 @@ limitations under the License. package _package import ( + "context" "fmt" "time" @@ -25,11 +26,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" - "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type UpdateSubCommand struct { @@ -53,7 +52,7 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { opts.pkgName = input.String(flagkey.PkgName) - _, opts.pkgNamespace, err = util.GetResourceNamespace(input, flagkey.NamespacePackage) + _, opts.pkgNamespace, err = opts.GetResourceNamespace(input, flagkey.NamespacePackage) if err != nil { return fv1.AggregateValidationErrors("Environment", err) } @@ -62,17 +61,17 @@ func (opts *UpdateSubCommand) complete(input cli.Input) (err error) { } func (opts *UpdateSubCommand) run(input cli.Input) error { - pkg, err := opts.Client().V1().Package().Get(&metav1.ObjectMeta{ - Namespace: opts.pkgNamespace, - Name: opts.pkgName, - }) + pkg, err := opts.Client().FissionClientSet.CoreV1().Packages(opts.pkgNamespace).Get(input.Context(), opts.pkgName, metav1.GetOptions{}) + if err != nil { + return err + } if err != nil { return errors.Wrap(err, "get package") } forceUpdate := input.Bool(flagkey.PkgForce) - fnList, err := GetFunctionsByPackage(opts.Client(), pkg.ObjectMeta.Name, pkg.ObjectMeta.Namespace) + fnList, err := GetFunctionsByPackage(input.Context(), opts.Client(), pkg.ObjectMeta.Name, pkg.ObjectMeta.Namespace) if err != nil { return errors.Wrap(err, "error getting function list") } @@ -87,7 +86,7 @@ func (opts *UpdateSubCommand) run(input cli.Input) error { } if pkg.ObjectMeta.ResourceVersion != newPkgMeta.ResourceVersion { - err = UpdateFunctionPackageResourceVersion(opts.Client(), newPkgMeta, fnList...) + err = UpdateFunctionPackageResourceVersion(input.Context(), opts.Client(), newPkgMeta, fnList...) if err != nil { return errors.Wrap(err, "error updating function package reference resource version") } @@ -96,7 +95,7 @@ func (opts *UpdateSubCommand) run(input cli.Input) error { return nil } -func UpdatePackage(input cli.Input, client client.Interface, pkg *fv1.Package) (*metav1.ObjectMeta, error) { +func UpdatePackage(input cli.Input, client cmd.Client, pkg *fv1.Package) (*metav1.ObjectMeta, error) { envName := input.String(flagkey.PkgEnvironment) srcArchiveFiles := input.StringSlice(flagkey.PkgSrcArchive) deployArchiveFiles := input.StringSlice(flagkey.PkgDeployArchive) @@ -175,23 +174,23 @@ func UpdatePackage(input cli.Input, client client.Interface, pkg *fv1.Package) ( } } - newPkgMeta, err := client.V1().Package().Update(pkg) + newPkgMeta, err := client.FissionClientSet.CoreV1().Packages(pkg.ObjectMeta.Namespace).Update(input.Context(), pkg, metav1.UpdateOptions{}) if err != nil { return nil, errors.Wrap(err, "update package") } fmt.Printf("Package '%v' updated\n", newPkgMeta.GetName()) - return newPkgMeta, err + return &newPkgMeta.ObjectMeta, err } -func UpdateFunctionPackageResourceVersion(client client.Interface, pkgMeta *metav1.ObjectMeta, fnList ...fv1.Function) error { +func UpdateFunctionPackageResourceVersion(ctx context.Context, client cmd.Client, pkgMeta *metav1.ObjectMeta, fnList ...fv1.Function) error { errs := &multierror.Error{} // update resource version of package reference of functions that shared the same package for _, fn := range fnList { fn.Spec.Package.PackageRef.ResourceVersion = pkgMeta.ResourceVersion - _, err := client.V1().Function().Update(&fn) + _, err := client.FissionClientSet.CoreV1().Functions(fn.ObjectMeta.Namespace).Update(ctx, &fn, metav1.UpdateOptions{}) if err != nil { errs = multierror.Append(errs, errors.Wrapf(err, "error updating package resource version of function '%v'", fn.ObjectMeta.Name)) } @@ -200,15 +199,15 @@ func UpdateFunctionPackageResourceVersion(client client.Interface, pkgMeta *meta return errs.ErrorOrNil() } -func updatePackageStatus(client client.Interface, pkg *fv1.Package, status fv1.BuildStatus) (*metav1.ObjectMeta, error) { +func updatePackageStatus(ctx context.Context, client cmd.Client, pkg *fv1.Package, status fv1.BuildStatus) (*metav1.ObjectMeta, error) { switch status { case fv1.BuildStatusNone, fv1.BuildStatusPending, fv1.BuildStatusRunning, fv1.BuildStatusSucceeded, fv1.CanaryConfigStatusAborted: pkg.Status = fv1.PackageStatus{ BuildStatus: status, LastUpdateTimestamp: metav1.Time{Time: time.Now().UTC()}, } - pkg, err := client.V1().Package().Update(pkg) - return pkg, err + pkg, err := client.FissionClientSet.CoreV1().Packages(pkg.Namespace).Update(ctx, pkg, metav1.UpdateOptions{}) + return &pkg.ObjectMeta, err } return nil, errors.New("unknown package status") } diff --git a/pkg/fission-cli/cmd/package/util/util.go b/pkg/fission-cli/cmd/package/util/util.go index c8c36f29..8ebcdd2d 100644 --- a/pkg/fission-cli/cmd/package/util/util.go +++ b/pkg/fission-cli/cmd/package/util/util.go @@ -31,11 +31,13 @@ import ( fv1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/controller/client" + "github.com/fission/fission/pkg/fission-cli/cmd" + "github.com/fission/fission/pkg/fission-cli/util" storageSvcClient "github.com/fission/fission/pkg/storagesvc/client" "github.com/fission/fission/pkg/utils" ) -func UploadArchiveFile(ctx context.Context, client client.Interface, fileName string) (*fv1.Archive, error) { +func UploadArchiveFile(ctx context.Context, client cmd.Client, fileName string) (*fv1.Archive, error) { var archive fv1.Archive size, err := utils.FileSize(fileName) @@ -50,26 +52,24 @@ func UploadArchiveFile(ctx context.Context, client client.Interface, fileName st return nil, err } } else { - u := strings.TrimSuffix(client.ServerURL(), "/") + "/proxy/storage" - ssClient := storageSvcClient.MakeClient(u) + storagesvcURL, err := util.GetStorageURL(ctx, client) + if err != nil { + return nil, errors.Wrapf(err, "error getting fission storage service URL") + } + + storageClient := storageSvcClient.MakeClient(storagesvcURL.String()) // TODO add a progress bar - id, err := ssClient.Upload(ctx, fileName, nil) + id, err := storageClient.Upload(ctx, fileName, nil) if err != nil { - return nil, errors.Wrapf(err, "error uploading file %v", fileName) + return nil, errors.Wrapf(err, "error uploading to fission storage service") } - storageSvc, err := client.V1().Misc().GetSvcURL("application=fission-storage") - storageSvcURL := "http://" + storageSvc + archiveURL, err := getArchiveURL(ctx, client, id, storagesvcURL) if err != nil { - return nil, errors.Wrapf(err, "error getting fission storage service name") + return nil, errors.Wrapf(err, "could not get URL of archive") } - // We make a new client with actual URL of Storage service so that the URL is not - // pointing to 127.0.0.1 i.e. proxy. DON'T reuse previous ssClient - pkgClient := storageSvcClient.MakeClient(storageSvcURL) - archiveURL := pkgClient.GetUrl(id) - archive.Type = fv1.ArchiveTypeUrl archive.URL = archiveURL @@ -84,6 +84,42 @@ func UploadArchiveFile(ctx context.Context, client client.Interface, fileName st return &archive, nil } +func getArchiveURL(ctx context.Context, client cmd.Client, archiveID string, serverURL *url.URL) (archiveURL string, err error) { + relativeURL, _ := url.Parse(util.FISSION_STORAGE_URI) + + queryString := relativeURL.Query() + queryString.Set("id", archiveID) + relativeURL.RawQuery = queryString.Encode() + + storageAccessURL := serverURL.ResolveReference(relativeURL) + + resp, err := http.Head(storageAccessURL.String()) + if err != nil { + return "", err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("error getting URL. Exited with Status: %s", resp.Status) + } + + storageType := resp.Header.Get("X-FISSION-STORAGETYPE") + + if storageType == "local" { + storageSvc, err := util.GetSvcName(ctx, client.KubernetesClient, "fission-storage") + if err != nil { + return "", err + } + storagesvcURL := "http://" + storageSvc + client := storageSvcClient.MakeClient(storagesvcURL) + return client.GetUrl(archiveID), nil + } else if storageType == "s3" { + storageBucket := resp.Header.Get("X-FISSION-BUCKET") + s3url := fmt.Sprintf("https://%s.s3.amazonaws.com/%s", storageBucket, archiveID) + return s3url, nil + } + return "", nil +} func GetContents(filePath string) ([]byte, error) { code, err := os.ReadFile(filePath) if err != nil { @@ -133,6 +169,42 @@ func DownloadURL(fileUrl string) (io.ReadCloser, error) { return resp.Body, nil } +func DownloadStrorageURL(ctx context.Context, client cmd.Client, fileUrl string) (io.ReadCloser, error) { + var resp *http.Response + storageSvc, err := util.GetSvcName(ctx, client.KubernetesClient, "fission-storage") + if err != nil { + return nil, err + } + + if strings.HasPrefix(fileUrl, "http://"+storageSvc+"/v1/archive?id=") { + url, err := url.Parse(fileUrl) + if err != nil { + return nil, err + } + id := url.Query().Get("id") + storageAccessURL, err := util.GetStorageURL(ctx, client) + if err != nil { + return nil, err + } + + client := storageSvcClient.MakeClient(storageAccessURL.String()) + resp, err = client.GetFile(ctx, id) + if err != nil { + return nil, err + } + } else { + resp, err = http.Get(fileUrl) + } + + if err != nil { + return nil, err + } + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("%v - HTTP response returned non 200 status", resp.StatusCode) + } + return resp.Body, nil +} + func WriteArchiveToFile(fileName string, reader io.Reader) error { tmpDir, err := utils.GetTempDir() if err != nil { diff --git a/pkg/fission-cli/cmd/spec/apply.go b/pkg/fission-cli/cmd/spec/apply.go index 1313d07a..377e80cf 100644 --- a/pkg/fission-cli/cmd/spec/apply.go +++ b/pkg/fission-cli/cmd/spec/apply.go @@ -32,7 +32,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" - "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" pkgutil "github.com/fission/fission/pkg/fission-cli/cmd/package/util" @@ -71,7 +70,7 @@ func (opts *ApplySubCommand) do(input cli.Input) error { func (opts *ApplySubCommand) insertNamespace(input cli.Input, fr *FissionResources) error { result := utils.MultiErrorWithFormat() - _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + _, currentNS, err := opts.GetResourceNamespace(input, flagkey.NamespaceEnvironment) if err != nil { return fv1.AggregateValidationErrors("Environment", err) } @@ -196,7 +195,7 @@ func (opts *ApplySubCommand) run(input cli.Input) error { } // make changes to the cluster based on the specs - pkgMetas, as, err := applyResources(input.Context(), opts.Client(), specDir, fr, deleteResources, input.Bool(flagkey.SpecAllowConflicts)) + pkgMetas, as, err := applyResources(input, opts.Client(), specDir, fr, deleteResources, input.Bool(flagkey.SpecAllowConflicts)) if err != nil { return errors.Wrap(err, "error applying specs") } @@ -349,7 +348,7 @@ func pluralize(num int, word string) string { } // applyArchives figures out the set of archives that need to be uploaded, and uploads them. -func applyArchives(ctx context.Context, fclient client.Interface, specDir string, fr *FissionResources) error { +func applyArchives(input cli.Input, fclient cmd.Client, specDir string, fr *FissionResources) error { // archive:// URL -> archive map. archiveFiles := make(map[string]fv1.Archive) @@ -369,11 +368,11 @@ func applyArchives(ctx context.Context, fclient client.Interface, specDir string // get list of packages, make content-indexed map of available archives availableArchives := make(map[string]string) // (sha256 -> url) - pkgs, err := fclient.V1().Package().List(metav1.NamespaceAll) + pkgs, err := fclient.FissionClientSet.CoreV1().Packages(metav1.NamespaceAll).List(input.Context(), metav1.ListOptions{}) if err != nil { return err } - for _, pkg := range pkgs { + for _, pkg := range pkgs.Items { for _, ar := range []fv1.Archive{pkg.Spec.Source, pkg.Spec.Deployment} { if ar.Type == fv1.ArchiveTypeUrl && len(ar.URL) > 0 { availableArchives[ar.Checksum.Sum] = ar.URL @@ -395,7 +394,7 @@ func applyArchives(ctx context.Context, fclient client.Interface, specDir string // doesn't exist, upload fmt.Printf("uploading archive %v\n", name) // ar.URL is actually a local filename at this stage - uploadedAr, err := pkgutil.UploadArchiveFile(ctx, fclient, ar.URL) + uploadedAr, err := pkgutil.UploadArchiveFile(input.Context(), fclient, ar.URL) if err != nil { return err } @@ -422,23 +421,23 @@ func applyArchives(ctx context.Context, fclient client.Interface, specDir string } // applyResources applies the given set of fission resources. -func applyResources(ctx context.Context, fclient client.Interface, specDir string, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, map[string]ResourceApplyStatus, error) { +func applyResources(input cli.Input, fclient cmd.Client, specDir string, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, map[string]ResourceApplyStatus, error) { applyStatus := make(map[string]ResourceApplyStatus) // upload archives that need to be uploaded. Changes archive references in fr.Packages. - err := applyArchives(ctx, fclient, specDir, fr) + err := applyArchives(input, fclient, specDir, fr) if err != nil { return nil, nil, err } - _, ras, err := applyEnvironments(fclient, fr, delete, specAllowConflicts) + _, ras, err := applyEnvironments(input.Context(), fclient, fr, delete, specAllowConflicts) if err != nil { return nil, nil, errors.Wrap(err, "environment apply failed") } applyStatus["environment"] = *ras - pkgMeta, ras, err := applyPackages(fclient, fr, delete, specAllowConflicts) + pkgMeta, ras, err := applyPackages(input.Context(), fclient, fr, delete, specAllowConflicts) if err != nil { return nil, nil, errors.Wrap(err, "package apply failed") } @@ -467,31 +466,31 @@ func applyResources(ctx context.Context, fclient client.Interface, specDir strin fr.Functions[i].Spec.Package.PackageRef.ResourceVersion = m.ResourceVersion } - _, ras, err = applyFunctions(fclient, fr, delete, specAllowConflicts) + _, ras, err = applyFunctions(input.Context(), fclient, fr, delete, specAllowConflicts) if err != nil { return nil, nil, errors.Wrap(err, "function apply failed") } applyStatus["function"] = *ras - _, ras, err = applyHTTPTriggers(fclient, fr, delete, specAllowConflicts) + _, ras, err = applyHTTPTriggers(input.Context(), fclient, fr, delete, specAllowConflicts) if err != nil { return nil, nil, errors.Wrap(err, "HTTPTrigger apply failed") } applyStatus["HTTPTrigger"] = *ras - _, ras, err = applyKubernetesWatchTriggers(fclient, fr, delete, specAllowConflicts) + _, ras, err = applyKubernetesWatchTriggers(input.Context(), fclient, fr, delete, specAllowConflicts) if err != nil { return nil, nil, errors.Wrap(err, "KubernetesWatchTrigger apply failed") } applyStatus["KubernetesWatchTrigger"] = *ras - _, ras, err = applyTimeTriggers(fclient, fr, delete, specAllowConflicts) + _, ras, err = applyTimeTriggers(input.Context(), fclient, fr, delete, specAllowConflicts) if err != nil { return nil, nil, errors.Wrap(err, "TimeTrigger apply failed") } applyStatus["TimeTrigger"] = *ras - _, ras, err = applyMessageQueueTriggers(fclient, fr, delete, specAllowConflicts) + _, ras, err = applyMessageQueueTriggers(input.Context(), fclient, fr, delete, specAllowConflicts) if err != nil { return nil, nil, errors.Wrap(err, "MessageQueueTrigger apply failed") } @@ -626,7 +625,7 @@ func hasDeploymentConfig(m *metav1.ObjectMeta, fr *FissionResources) bool { return false } -func waitForPackageBuild(fclient client.Interface, pkg *fv1.Package) (*fv1.Package, error) { +func waitForPackageBuild(ctx context.Context, fclient cmd.Client, pkg *fv1.Package) (*fv1.Package, error) { start := time.Now() for { if pkg.Status.BuildStatus != fv1.BuildStatusRunning { @@ -640,16 +639,16 @@ func waitForPackageBuild(fclient client.Interface, pkg *fv1.Package) (*fv1.Packa time.Sleep(time.Second) var err error - pkg, err = fclient.V1().Package().Get(&pkg.ObjectMeta) + pkg, err = fclient.FissionClientSet.CoreV1().Packages(pkg.ObjectMeta.Namespace).Get(ctx, pkg.ObjectMeta.Name, metav1.GetOptions{}) if err != nil { return nil, err } } } -func applyPackages(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { +func applyPackages(ctx context.Context, fclient cmd.Client, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { // get list - allObjs, err := fclient.V1().Package().List(metav1.NamespaceAll) + allObjs, err := fclient.FissionClientSet.CoreV1().Packages(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { return nil, nil, err } @@ -657,9 +656,9 @@ func applyPackages(fclient client.Interface, fr *FissionResources, delete bool, // filter objs := make([]fv1.Package, 0) if specAllowConflicts { - objs = allObjs + objs = allObjs.Items } else { - for _, o := range allObjs { + for _, o := range allObjs.Items { if hasDeploymentConfig(&o.ObjectMeta, fr) { objs = append(objs, o) } @@ -711,7 +710,7 @@ func applyPackages(fclient client.Interface, fr *FissionResources, delete bool, // We may be racing against the package builder to update the // package (a previous version might have been getting built). So, // wait for the package to have a non-running build status. - pkg, err := waitForPackageBuild(fclient, &o) + pkg, err := waitForPackageBuild(ctx, fclient, &o) if err != nil { // log and ignore console.Warn(fmt.Sprintf("Error waiting for package '%v' build, ignoring", o.ObjectMeta.Name)) @@ -723,23 +722,24 @@ func applyPackages(fclient client.Interface, fr *FissionResources, delete bool, pkg.Status.BuildStatus = fv1.BuildStatusPending } - newmeta, err := fclient.V1().Package().Update(pkg) + newmeta, err := fclient.FissionClientSet.CoreV1().Packages(pkg.ObjectMeta.Namespace).Update(ctx, pkg, metav1.UpdateOptions{}) if err != nil { return nil, nil, err // TODO check for resourceVersion conflict errors and retry } - ras.Updated = append(ras.Updated, newmeta) + ras.Updated = append(ras.Updated, &newmeta.ObjectMeta) // keep track of metadata in case we need to create a reference to it - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } else { + // create - newmeta, err := fclient.V1().Package().Create(&o) + newmeta, err := fclient.FissionClientSet.CoreV1().Packages(o.ObjectMeta.Namespace).Create(ctx, &o, metav1.CreateOptions{}) if err != nil { return nil, nil, err } - ras.Created = append(ras.Created, newmeta) - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + ras.Created = append(ras.Created, &newmeta.ObjectMeta) + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } @@ -749,7 +749,7 @@ func applyPackages(fclient client.Interface, fr *FissionResources, delete bool, for _, o := range objs { _, wanted := desired[mapKey(&o.ObjectMeta)] if !wanted { - err := fclient.V1().Package().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().Packages(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil { return nil, nil, err } @@ -762,9 +762,9 @@ func applyPackages(fclient client.Interface, fr *FissionResources, delete bool, return metadataMap, &ras, nil } -func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { +func applyFunctions(ctx context.Context, fclient cmd.Client, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { // get list - allObjs, err := fclient.V1().Function().List(metav1.NamespaceAll) + allObjs, err := fclient.FissionClientSet.CoreV1().Functions(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { return nil, nil, err } @@ -772,9 +772,9 @@ func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool, // filter objs := make([]fv1.Function, 0) if specAllowConflicts { - objs = allObjs + objs = allObjs.Items } else { - for _, o := range allObjs { + for _, o := range allObjs.Items { if hasDeploymentConfig(&o.ObjectMeta, fr) { objs = append(objs, o) } @@ -811,22 +811,22 @@ func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool, } else { // update o.ObjectMeta.ResourceVersion = existingObj.ObjectMeta.ResourceVersion - newmeta, err := fclient.V1().Function().Update(&o) + newmeta, err := fclient.FissionClientSet.CoreV1().Functions(o.ObjectMeta.Namespace).Update(ctx, &o, metav1.UpdateOptions{}) if err != nil { return nil, nil, err } - ras.Updated = append(ras.Updated, newmeta) + ras.Updated = append(ras.Updated, &newmeta.ObjectMeta) // keep track of metadata in case we need to create a reference to it - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } else { // create - newmeta, err := fclient.V1().Function().Create(&o) + newmeta, err := fclient.FissionClientSet.CoreV1().Functions(o.ObjectMeta.Namespace).Create(ctx, &o, metav1.CreateOptions{}) if err != nil { return nil, nil, err } - ras.Created = append(ras.Created, newmeta) - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + ras.Created = append(ras.Created, &newmeta.ObjectMeta) + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } @@ -836,7 +836,7 @@ func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool, for _, o := range objs { _, wanted := desired[mapKey(&o.ObjectMeta)] if !wanted { - err := fclient.V1().Function().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().Functions(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil { return nil, nil, err } @@ -849,9 +849,9 @@ func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool, return metadataMap, &ras, nil } -func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { +func applyEnvironments(ctx context.Context, fclient cmd.Client, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { // get list - allObjs, err := fclient.V1().Environment().List(metav1.NamespaceAll) + allObjs, err := fclient.FissionClientSet.CoreV1().Environments(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { return nil, nil, err } @@ -859,9 +859,9 @@ func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bo // filter objs := make([]fv1.Environment, 0) if specAllowConflicts { - objs = allObjs + objs = allObjs.Items } else { - for _, o := range allObjs { + for _, o := range allObjs.Items { if hasDeploymentConfig(&o.ObjectMeta, fr) { objs = append(objs, o) } @@ -898,22 +898,22 @@ func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bo } else { // update o.ObjectMeta.ResourceVersion = existingObj.ObjectMeta.ResourceVersion - newmeta, err := fclient.V1().Environment().Update(&o) + newmeta, err := fclient.FissionClientSet.CoreV1().Environments(o.ObjectMeta.Namespace).Update(ctx, &o, metav1.UpdateOptions{}) if err != nil { return nil, nil, err } - ras.Updated = append(ras.Updated, newmeta) + ras.Updated = append(ras.Updated, &newmeta.ObjectMeta) // keep track of metadata in case we need to create a reference to it - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } else { // create - newmeta, err := fclient.V1().Environment().Create(&o) + newmeta, err := fclient.FissionClientSet.CoreV1().Environments(o.ObjectMeta.Namespace).Create(ctx, &o, metav1.CreateOptions{}) if err != nil { return nil, nil, err } - ras.Created = append(ras.Created, newmeta) - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + ras.Created = append(ras.Created, &newmeta.ObjectMeta) + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } @@ -923,7 +923,7 @@ func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bo for _, o := range objs { _, wanted := desired[mapKey(&o.ObjectMeta)] if !wanted { - err := fclient.V1().Environment().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().Environments(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Namespace, metav1.DeleteOptions{}) if err != nil { return nil, nil, err } @@ -936,9 +936,9 @@ func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bo return metadataMap, &ras, nil } -func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { +func applyHTTPTriggers(ctx context.Context, fclient cmd.Client, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { // get list - allObjs, err := fclient.V1().HTTPTrigger().List(metav1.NamespaceAll) + allObjs, err := fclient.FissionClientSet.CoreV1().HTTPTriggers(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { return nil, nil, err } @@ -946,9 +946,9 @@ func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bo // filter objs := make([]fv1.HTTPTrigger, 0) if specAllowConflicts { - objs = allObjs + objs = allObjs.Items } else { - for _, o := range allObjs { + for _, o := range allObjs.Items { if hasDeploymentConfig(&o.ObjectMeta, fr) { objs = append(objs, o) } @@ -983,24 +983,34 @@ func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bo // nothing to do on the server metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta } else { - // update - o.ObjectMeta.ResourceVersion = existingObj.ObjectMeta.ResourceVersion - newmeta, err := fclient.V1().HTTPTrigger().Update(&o) + + err := util.CheckHTTPTriggerDuplicates(ctx, fclient, &o) if err != nil { return nil, nil, err } - ras.Updated = append(ras.Updated, newmeta) + // update + o.ObjectMeta.ResourceVersion = existingObj.ObjectMeta.ResourceVersion + newmeta, err := fclient.FissionClientSet.CoreV1().HTTPTriggers(o.ObjectMeta.Namespace).Update(ctx, &o, metav1.UpdateOptions{}) + if err != nil { + return nil, nil, err + } + ras.Updated = append(ras.Updated, &newmeta.ObjectMeta) // keep track of metadata in case we need to create a reference to it - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } else { - // create - newmeta, err := fclient.V1().HTTPTrigger().Create(&o) + + err := util.CheckHTTPTriggerDuplicates(ctx, fclient, &o) if err != nil { return nil, nil, err } - ras.Created = append(ras.Created, newmeta) - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + // create + newmeta, err := fclient.FissionClientSet.CoreV1().HTTPTriggers(o.ObjectMeta.Namespace).Create(ctx, &o, metav1.CreateOptions{}) + if err != nil { + return nil, nil, err + } + ras.Created = append(ras.Created, &newmeta.ObjectMeta) + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } @@ -1010,7 +1020,7 @@ func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bo for _, o := range objs { _, wanted := desired[mapKey(&o.ObjectMeta)] if !wanted { - err := fclient.V1().HTTPTrigger().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().HTTPTriggers(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil { return nil, nil, err } @@ -1023,9 +1033,9 @@ func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bo return metadataMap, &ras, nil } -func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { +func applyKubernetesWatchTriggers(ctx context.Context, fclient cmd.Client, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { // get list - allObjs, err := fclient.V1().KubeWatcher().List(metav1.NamespaceAll) + allObjs, err := fclient.FissionClientSet.CoreV1().KubernetesWatchTriggers(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { return nil, nil, err } @@ -1033,9 +1043,9 @@ func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources // filter objs := make([]fv1.KubernetesWatchTrigger, 0) if specAllowConflicts { - objs = allObjs + objs = allObjs.Items } else { - for _, o := range allObjs { + for _, o := range allObjs.Items { if hasDeploymentConfig(&o.ObjectMeta, fr) { objs = append(objs, o) } @@ -1072,22 +1082,22 @@ func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources } else { // update o.ObjectMeta.ResourceVersion = existingObj.ObjectMeta.ResourceVersion - newmeta, err := fclient.V1().KubeWatcher().Update(&o) + newmeta, err := fclient.FissionClientSet.CoreV1().KubernetesWatchTriggers(o.ObjectMeta.Namespace).Update(ctx, &o, metav1.UpdateOptions{}) if err != nil { return nil, nil, err } - ras.Updated = append(ras.Updated, newmeta) + ras.Updated = append(ras.Updated, &newmeta.ObjectMeta) // keep track of metadata in case we need to create a reference to it - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } else { // create - newmeta, err := fclient.V1().KubeWatcher().Create(&o) + newmeta, err := fclient.FissionClientSet.CoreV1().KubernetesWatchTriggers(o.ObjectMeta.Namespace).Create(ctx, &o, metav1.CreateOptions{}) if err != nil { return nil, nil, err } - ras.Created = append(ras.Created, newmeta) - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + ras.Created = append(ras.Created, &newmeta.ObjectMeta) + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } @@ -1097,7 +1107,7 @@ func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources for _, o := range objs { _, wanted := desired[mapKey(&o.ObjectMeta)] if !wanted { - err := fclient.V1().KubeWatcher().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().KubernetesWatchTriggers(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil { return nil, nil, err } @@ -1110,9 +1120,9 @@ func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources return metadataMap, &ras, nil } -func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { +func applyTimeTriggers(ctx context.Context, fclient cmd.Client, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { // get list - allObjs, err := fclient.V1().TimeTrigger().List(metav1.NamespaceAll) + allObjs, err := fclient.FissionClientSet.CoreV1().TimeTriggers(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { return nil, nil, err } @@ -1120,9 +1130,9 @@ func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bo // filter objs := make([]fv1.TimeTrigger, 0) if specAllowConflicts { - objs = allObjs + objs = allObjs.Items } else { - for _, o := range allObjs { + for _, o := range allObjs.Items { if hasDeploymentConfig(&o.ObjectMeta, fr) { objs = append(objs, o) } @@ -1159,22 +1169,22 @@ func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bo } else { // update o.ObjectMeta.ResourceVersion = existingObj.ObjectMeta.ResourceVersion - newmeta, err := fclient.V1().TimeTrigger().Update(&o) + newmeta, err := fclient.FissionClientSet.CoreV1().TimeTriggers(o.ObjectMeta.Namespace).Update(ctx, &o, metav1.UpdateOptions{}) if err != nil { return nil, nil, err } - ras.Updated = append(ras.Updated, newmeta) + ras.Updated = append(ras.Updated, &newmeta.ObjectMeta) // keep track of metadata in case we need to create a reference to it - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } else { // create - newmeta, err := fclient.V1().TimeTrigger().Create(&o) + newmeta, err := fclient.FissionClientSet.CoreV1().TimeTriggers(o.Namespace).Create(ctx, &o, metav1.CreateOptions{}) if err != nil { return nil, nil, err } - ras.Created = append(ras.Created, newmeta) - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + ras.Created = append(ras.Created, &newmeta.ObjectMeta) + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } @@ -1184,7 +1194,7 @@ func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bo for _, o := range objs { _, wanted := desired[mapKey(&o.ObjectMeta)] if !wanted { - err := fclient.V1().TimeTrigger().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().TimeTriggers(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil { return nil, nil, err } @@ -1197,9 +1207,9 @@ func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bo return metadataMap, &ras, nil } -func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { +func applyMessageQueueTriggers(ctx context.Context, fclient cmd.Client, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) { // get list - allObjs, err := fclient.V1().MessageQueueTrigger().List("", metav1.NamespaceAll) + allObjs, err := fclient.FissionClientSet.CoreV1().MessageQueueTriggers(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { return nil, nil, err } @@ -1207,9 +1217,9 @@ func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, d // filter objs := make([]fv1.MessageQueueTrigger, 0) if specAllowConflicts { - objs = allObjs + objs = allObjs.Items } else { - for _, o := range allObjs { + for _, o := range allObjs.Items { if hasDeploymentConfig(&o.ObjectMeta, fr) { objs = append(objs, o) } @@ -1246,22 +1256,22 @@ func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, d } else { // update o.ObjectMeta.ResourceVersion = existingObj.ObjectMeta.ResourceVersion - newmeta, err := fclient.V1().MessageQueueTrigger().Update(&o) + newmeta, err := fclient.FissionClientSet.CoreV1().MessageQueueTriggers(o.ObjectMeta.Namespace).Update(ctx, &o, metav1.UpdateOptions{}) if err != nil { return nil, nil, err } - ras.Updated = append(ras.Updated, newmeta) + ras.Updated = append(ras.Updated, &newmeta.ObjectMeta) // keep track of metadata in case we need to create a reference to it - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } else { // create - newmeta, err := fclient.V1().MessageQueueTrigger().Create(&o) + newmeta, err := fclient.FissionClientSet.CoreV1().MessageQueueTriggers(o.ObjectMeta.Namespace).Create(ctx, &o, metav1.CreateOptions{}) if err != nil { return nil, nil, err } - ras.Created = append(ras.Created, newmeta) - metadataMap[mapKey(&o.ObjectMeta)] = *newmeta + ras.Created = append(ras.Created, &newmeta.ObjectMeta) + metadataMap[mapKey(&o.ObjectMeta)] = newmeta.ObjectMeta } } @@ -1271,7 +1281,7 @@ func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, d for _, o := range objs { _, wanted := desired[mapKey(&o.ObjectMeta)] if !wanted { - err := fclient.V1().MessageQueueTrigger().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().MessageQueueTriggers(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil { return nil, nil, err } diff --git a/pkg/fission-cli/cmd/spec/buildwatch.go b/pkg/fission-cli/cmd/spec/buildwatch.go index 69f29bec..e752467d 100644 --- a/pkg/fission-cli/cmd/spec/buildwatch.go +++ b/pkg/fission-cli/cmd/spec/buildwatch.go @@ -25,7 +25,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" - "github.com/fission/fission/pkg/controller/client" + "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd/package/util" ) @@ -33,8 +33,7 @@ type ( // packageBuildWatcher is used to watch a set of in-progress builds. packageBuildWatcher struct { // fission client - fclient client.Interface - + fclient cmd.Client // set of packages already printed, ensures we don't duplicate the notifications finished map[string]bool @@ -43,7 +42,7 @@ type ( } ) -func makePackageBuildWatcher(fclient client.Interface) *packageBuildWatcher { +func makePackageBuildWatcher(fclient cmd.Client) *packageBuildWatcher { return &packageBuildWatcher{ fclient: fclient, finished: make(map[string]bool), @@ -67,7 +66,7 @@ func (w *packageBuildWatcher) watch(ctx context.Context) { } // pull list of packages (TODO: convert to watch) - pkgs, err := w.fclient.V1().Package().List(metav1.NamespaceAll) + pkgs, err := w.fclient.FissionClientSet.CoreV1().Packages(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { fmt.Printf("Getting list of packages: %v", err) os.Exit(1) @@ -77,7 +76,7 @@ func (w *packageBuildWatcher) watch(ctx context.Context) { // build status (either succeeded or failed; not "none") keepWaiting := false buildpkgs := make([]fv1.Package, 0) - for _, pkg := range pkgs { + for _, pkg := range pkgs.Items { _, ok := w.pkgMeta[mapKey(&pkg.ObjectMeta)] if !ok { continue diff --git a/pkg/fission-cli/cmd/spec/destroy.go b/pkg/fission-cli/cmd/spec/destroy.go index 9a831a76..efa622e1 100644 --- a/pkg/fission-cli/cmd/spec/destroy.go +++ b/pkg/fission-cli/cmd/spec/destroy.go @@ -17,13 +17,14 @@ limitations under the License. package spec import ( + "context" "fmt" "strings" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" - "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/console" @@ -68,14 +69,14 @@ func (opts *DestroySubCommand) run(input cli.Input) error { emptyFr.DeploymentConfig = fr.DeploymentConfig // "apply" the empty state - err = forceDeleteResources(opts.Client(), &emptyFr) + err = forceDeleteResources(input.Context(), opts.Client(), &emptyFr) if err != nil { return errors.Wrap(err, "error deleting resources") } return nil } forceDelete := input.Bool(flagkey.ForceDelete) - err = deleteResources(opts.Client(), fr, forceDelete) + err = deleteResources(input.Context(), opts.Client(), fr, forceDelete) if err != nil { return errors.Wrap(err, "error deleting resources") } @@ -83,41 +84,41 @@ func (opts *DestroySubCommand) run(input cli.Input) error { return nil } -func forceDeleteResources(fclient client.Interface, fr *FissionResources) error { +func forceDeleteResources(ctx context.Context, fclient cmd.Client, fr *FissionResources) error { var err error - _, _, err = applyHTTPTriggers(fclient, fr, true, false) + _, _, err = applyHTTPTriggers(ctx, fclient, fr, true, false) if err != nil { return errors.Wrap(err, "HTTPTrigger delete failed") } - _, _, err = applyKubernetesWatchTriggers(fclient, fr, true, false) + _, _, err = applyKubernetesWatchTriggers(ctx, fclient, fr, true, false) if err != nil { return errors.Wrap(err, "KubernetesWatchTrigger delete failed") } - _, _, err = applyTimeTriggers(fclient, fr, true, false) + _, _, err = applyTimeTriggers(ctx, fclient, fr, true, false) if err != nil { return errors.Wrap(err, "TimeTrigger delete failed") } - _, _, err = applyMessageQueueTriggers(fclient, fr, true, false) + _, _, err = applyMessageQueueTriggers(ctx, fclient, fr, true, false) if err != nil { return errors.Wrap(err, "MessageQueueTrigger delete failed") } - _, _, err = applyFunctions(fclient, fr, true, false) + _, _, err = applyFunctions(ctx, fclient, fr, true, false) if err != nil { return errors.Wrap(err, "function delete failed") } - _, _, err = applyPackages(fclient, fr, true, false) + _, _, err = applyPackages(ctx, fclient, fr, true, false) if err != nil { return errors.Wrap(err, "package delete failed") } - _, _, err = applyEnvironments(fclient, fr, true, false) + _, _, err = applyEnvironments(ctx, fclient, fr, true, false) if err != nil { return errors.Wrap(err, "environment delete failed") } @@ -131,7 +132,7 @@ func (opts *DestroySubCommand) insertNSToResource(input cli.Input, fr *FissionRe result := utils.MultiErrorWithFormat() - _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + _, currentNS, err := opts.GetResourceNamespace(input, flagkey.NamespaceEnvironment) if err != nil { return fv1.AggregateValidationErrors("Environment", err) } @@ -175,41 +176,41 @@ func (opts *DestroySubCommand) insertNSToResource(input cli.Input, fr *FissionRe return result.ErrorOrNil() } -func deleteResources(fclient client.Interface, fr *FissionResources, forceDelete bool) error { +func deleteResources(ctx context.Context, fclient cmd.Client, fr *FissionResources, forceDelete bool) error { var err error - err = destroyHTTPTriggers(fclient, fr) + err = destroyHTTPTriggers(ctx, fclient, fr) if err != nil { return errors.Wrap(err, "HTTPTrigger delete failed") } - err = destroyKubernetesWatchTriggers(fclient, fr) + err = destroyKubernetesWatchTriggers(ctx, fclient, fr) if err != nil { return errors.Wrap(err, "KubernetesWatchTrigger delete failed") } - err = destroyTimeTriggers(fclient, fr) + err = destroyTimeTriggers(ctx, fclient, fr) if err != nil { return errors.Wrap(err, "TimeTrigger delete failed") } - err = destroyMessageQueueTriggers(fclient, fr) + err = destroyMessageQueueTriggers(ctx, fclient, fr) if err != nil { return errors.Wrap(err, "MessageQueueTrigger delete failed") } - err = destroyFunctions(fclient, fr) + err = destroyFunctions(ctx, fclient, fr) if err != nil { return errors.Wrap(err, "function delete failed") } - err = destroyPackages(fclient, fr) + err = destroyPackages(ctx, fclient, fr) if err != nil { return errors.Wrap(err, "package delete failed") } - err = destroyEnvironments(fclient, fr) + err = destroyEnvironments(ctx, fclient, fr) if err != nil { return errors.Wrap(err, "environment delete failed") } @@ -217,9 +218,9 @@ func deleteResources(fclient client.Interface, fr *FissionResources, forceDelete return nil } -func destroyHTTPTriggers(fclient client.Interface, fr *FissionResources) error { +func destroyHTTPTriggers(ctx context.Context, fclient cmd.Client, fr *FissionResources) error { for _, o := range fr.HttpTriggers { - err := fclient.V1().HTTPTrigger().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().HTTPTriggers(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil && strings.Contains(err.Error(), "not found") { console.Verbose(2, fmt.Sprintf("could not delete httptrigger: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) err = nil @@ -233,10 +234,10 @@ func destroyHTTPTriggers(fclient client.Interface, fr *FissionResources) error { return nil } -func destroyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources) error { +func destroyKubernetesWatchTriggers(ctx context.Context, fclient cmd.Client, fr *FissionResources) error { for _, o := range fr.KubernetesWatchTriggers { - err := fclient.V1().KubeWatcher().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().KubernetesWatchTriggers(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil && strings.Contains(err.Error(), "not found") { console.Verbose(2, fmt.Sprintf("could not delete watch: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) err = nil @@ -251,10 +252,10 @@ func destroyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResourc return nil } -func destroyTimeTriggers(fclient client.Interface, fr *FissionResources) error { +func destroyTimeTriggers(ctx context.Context, fclient cmd.Client, fr *FissionResources) error { for _, o := range fr.TimeTriggers { - err := fclient.V1().TimeTrigger().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().TimeTriggers(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil && strings.Contains(err.Error(), "not found") { console.Verbose(2, fmt.Sprintf("could not delete Time trigger: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) err = nil @@ -269,10 +270,10 @@ func destroyTimeTriggers(fclient client.Interface, fr *FissionResources) error { return nil } -func destroyMessageQueueTriggers(fclient client.Interface, fr *FissionResources) error { +func destroyMessageQueueTriggers(ctx context.Context, fclient cmd.Client, fr *FissionResources) error { for _, o := range fr.MessageQueueTriggers { - err := fclient.V1().MessageQueueTrigger().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().MessageQueueTriggers(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil && strings.Contains(err.Error(), "not found") { console.Verbose(2, fmt.Sprintf("could not delete Message trigger: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) err = nil @@ -287,10 +288,10 @@ func destroyMessageQueueTriggers(fclient client.Interface, fr *FissionResources) return nil } -func destroyFunctions(fclient client.Interface, fr *FissionResources) error { +func destroyFunctions(ctx context.Context, fclient cmd.Client, fr *FissionResources) error { for _, o := range fr.Functions { - err := fclient.V1().Function().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().Functions(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil && strings.Contains(err.Error(), "not found") { console.Verbose(2, fmt.Sprintf("could not delete Functions: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) err = nil @@ -305,10 +306,10 @@ func destroyFunctions(fclient client.Interface, fr *FissionResources) error { return nil } -func destroyPackages(fclient client.Interface, fr *FissionResources) error { +func destroyPackages(ctx context.Context, fclient cmd.Client, fr *FissionResources) error { for _, o := range fr.Packages { - err := fclient.V1().Package().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().Packages(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil && strings.Contains(err.Error(), "not found") { console.Verbose(2, fmt.Sprintf("could not delete Package: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) err = nil @@ -323,10 +324,10 @@ func destroyPackages(fclient client.Interface, fr *FissionResources) error { return nil } -func destroyEnvironments(fclient client.Interface, fr *FissionResources) error { +func destroyEnvironments(ctx context.Context, fclient cmd.Client, fr *FissionResources) error { for _, o := range fr.Environments { - err := fclient.V1().Environment().Delete(&o.ObjectMeta) + err := fclient.FissionClientSet.CoreV1().Environments(o.ObjectMeta.Namespace).Delete(ctx, o.ObjectMeta.Name, metav1.DeleteOptions{}) if err != nil && strings.Contains(err.Error(), "not found") { console.Verbose(2, fmt.Sprintf("could not delete Env: %s Namespace: %s", o.ObjectMeta.Name, o.ObjectMeta.Namespace)) err = nil diff --git a/pkg/fission-cli/cmd/spec/list.go b/pkg/fission-cli/cmd/spec/list.go index fd63d90d..129f4c1f 100644 --- a/pkg/fission-cli/cmd/spec/list.go +++ b/pkg/fission-cli/cmd/spec/list.go @@ -17,6 +17,7 @@ limitations under the License. package spec import ( + "context" "fmt" "os" "strings" @@ -24,9 +25,9 @@ import ( "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" - "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" @@ -60,27 +61,27 @@ func (opts *ListSubCommand) run(input cli.Input) error { deployID = fr.DeploymentConfig.UID } - _, currentNS, err := util.GetResourceNamespace(input, flagkey.NamespaceEnvironment) + _, currentNS, err := opts.GetResourceNamespace(input, flagkey.NamespaceEnvironment) if err != nil { return fv1.AggregateValidationErrors("Environment", err) } if input.Bool(flagkey.AllNamespaces) { - return opts.getResource(input, "", deployID) - } else { - return opts.getResource(input, currentNS, deployID) + currentNS = metav1.NamespaceAll } + return opts.getResource(input, currentNS, deployID) + } func (opts *ListSubCommand) getResource(input cli.Input, namespace string, deployID string) (err error) { var allfn []fv1.Function printNS := namespace - if printNS == "" { + if printNS == metav1.NamespaceAll { printNS = "all" } - allfn, err = getAllFunctions(opts.Client(), namespace) + allfn, err = getAllFunctions(input.Context(), opts.Client(), namespace) if err != nil { return errors.Wrap(err, fmt.Sprintf("error getting Functions from %s namespaces", printNS)) } @@ -88,7 +89,7 @@ func (opts *ListSubCommand) getResource(input cli.Input, namespace string, deplo ShowFunctions(specfns) var allenvs []fv1.Environment - allenvs, err = getAllEnvironments(opts.Client(), namespace) + allenvs, err = getAllEnvironments(input.Context(), opts.Client(), namespace) if err != nil { return errors.Wrap(err, fmt.Sprintf("error getting Environments from %s namespaces", printNS)) } @@ -96,7 +97,7 @@ func (opts *ListSubCommand) getResource(input cli.Input, namespace string, deplo ShowEnvironments(specenvs) var pkglists []fv1.Package - pkglists, err = getAllPackages(opts.Client(), namespace) + pkglists, err = getAllPackages(input.Context(), opts.Client(), namespace) if err != nil { return errors.Wrap(err, fmt.Sprintf("error getting Packages from %s namespaces", printNS)) } @@ -104,7 +105,7 @@ func (opts *ListSubCommand) getResource(input cli.Input, namespace string, deplo ShowPackages(specPkgs) var canaryCfgs []fv1.CanaryConfig - canaryCfgs, err = getAllCanaryConfigs(opts.Client(), namespace) + canaryCfgs, err = getAllCanaryConfigs(input.Context(), opts.Client(), namespace) if err != nil { return errors.Wrap(err, fmt.Sprintf("error getting Canary Config from %s namespaces", printNS)) } @@ -112,7 +113,7 @@ func (opts *ListSubCommand) getResource(input cli.Input, namespace string, deplo ShowCanaryConfigs(specCanaryCfgs) var hts []fv1.HTTPTrigger - hts, err = getAllHTTPTriggers(opts.Client(), namespace) + hts, err = getAllHTTPTriggers(input.Context(), opts.Client(), namespace) if err != nil { return errors.Wrap(err, fmt.Sprintf("error getting HTTP Triggers from %s namespaces", printNS)) } @@ -120,7 +121,7 @@ func (opts *ListSubCommand) getResource(input cli.Input, namespace string, deplo ShowHTTPTriggers(specHTTPTriggers) var mqts []fv1.MessageQueueTrigger - mqts, err = getAllMessageQueueTriggers(opts.Client(), input.String(flagkey.MqtMQType), namespace) + mqts, err = getAllMessageQueueTriggers(input.Context(), opts.Client(), input.String(flagkey.MqtMQType), namespace) if err != nil { return errors.Wrap(err, fmt.Sprintf("error getting MessageQueue Triggers from %s namespaces", printNS)) } @@ -128,7 +129,7 @@ func (opts *ListSubCommand) getResource(input cli.Input, namespace string, deplo ShowMQTriggers(specMessageQueueTriggers) var tts []fv1.TimeTrigger - tts, err = getAllTimeTriggers(opts.Client(), namespace) + tts, err = getAllTimeTriggers(input.Context(), opts.Client(), namespace) if err != nil { return errors.Wrap(err, fmt.Sprintf("error getting Time Triggers from %s namespaces", printNS)) } @@ -136,7 +137,7 @@ func (opts *ListSubCommand) getResource(input cli.Input, namespace string, deplo ShowTimeTriggers(specTimeTriggers) var kws []fv1.KubernetesWatchTrigger - kws, err = getAllKubeWatchTriggers(opts.Client(), namespace) + kws, err = getAllKubeWatchTriggers(input.Context(), opts.Client(), namespace) if err != nil { return errors.Wrap(err, fmt.Sprintf("error getting Kube Watchers from %s namespaces", printNS)) } @@ -420,73 +421,73 @@ func ShowAppliedKubeWatchers(ws []fv1.KubernetesWatchTrigger) { } // getAllFunctions get lists of functions in provided namespaces -func getAllFunctions(client client.Interface, namespace string) ([]fv1.Function, error) { - fns, err := client.V1().Function().List(namespace) +func getAllFunctions(ctx context.Context, client cmd.Client, namespace string) ([]fv1.Function, error) { + fns, err := client.FissionClientSet.CoreV1().Functions(namespace).List(ctx, metav1.ListOptions{}) if err != nil { return nil, errors.Errorf("Unable to get Functions %v", err.Error()) } - return fns, nil + return fns.Items, nil } // getAllEnvironments get lists of environments in all namespaces -func getAllEnvironments(client client.Interface, namespace string) ([]fv1.Environment, error) { - envs, err := client.V1().Environment().List(namespace) +func getAllEnvironments(ctx context.Context, client cmd.Client, namespace string) ([]fv1.Environment, error) { + envs, err := client.FissionClientSet.CoreV1().Environments(namespace).List(ctx, metav1.ListOptions{}) if err != nil { return nil, errors.Errorf("Unable to get Environments %v", err.Error()) } - return envs, nil + return envs.Items, nil } // getAllPackages get lists of packages in all namespaces -func getAllPackages(client client.Interface, namespace string) ([]fv1.Package, error) { - pkgList, err := client.V1().Package().List(namespace) +func getAllPackages(ctx context.Context, client cmd.Client, namespace string) ([]fv1.Package, error) { + pkgList, err := client.FissionClientSet.CoreV1().Packages(namespace).List(ctx, metav1.ListOptions{}) if err != nil { return nil, errors.Errorf("Unable to get Packages %v", err.Error()) } - return pkgList, nil + return pkgList.Items, nil } // getAllCanaryConfigs get lists of canary configs in all namespaces -func getAllCanaryConfigs(client client.Interface, namespace string) ([]fv1.CanaryConfig, error) { - canaryCfgs, err := client.V1().CanaryConfig().List(namespace) +func getAllCanaryConfigs(ctx context.Context, client cmd.Client, namespace string) ([]fv1.CanaryConfig, error) { + canaryCfgs, err := client.FissionClientSet.CoreV1().CanaryConfigs(namespace).List(ctx, metav1.ListOptions{}) if err != nil { return nil, errors.Errorf("Unable to get Canary Configs %v", err.Error()) } - return canaryCfgs, nil + return canaryCfgs.Items, nil } // getAllHTTPTriggers get lists of HTTP Triggers in all namespaces -func getAllHTTPTriggers(client client.Interface, namespace string) ([]fv1.HTTPTrigger, error) { - hts, err := client.V1().HTTPTrigger().List(namespace) +func getAllHTTPTriggers(ctx context.Context, client cmd.Client, namespace string) ([]fv1.HTTPTrigger, error) { + hts, err := client.FissionClientSet.CoreV1().HTTPTriggers(namespace).List(ctx, metav1.ListOptions{}) if err != nil { return nil, errors.Errorf("Unable to get HTTP Triggers %v", err.Error()) } - return hts, nil + return hts.Items, nil } // getAllMessageQueueTriggers get lists of MessageQueue Triggers in all namespaces -func getAllMessageQueueTriggers(client client.Interface, mqttype string, namespace string) ([]fv1.MessageQueueTrigger, error) { - mqts, err := client.V1().MessageQueueTrigger().List(mqttype, namespace) +func getAllMessageQueueTriggers(ctx context.Context, client cmd.Client, mqttype string, namespace string) ([]fv1.MessageQueueTrigger, error) { + mqts, err := client.FissionClientSet.CoreV1().MessageQueueTriggers(namespace).List(ctx, metav1.ListOptions{}) if err != nil { return nil, errors.Errorf("Unable to get MessageQueue Triggers %v", err.Error()) } - return mqts, nil + return mqts.Items, nil } // getAllTimeTriggers get lists of Time Triggers in all namespaces -func getAllTimeTriggers(client client.Interface, namespace string) ([]fv1.TimeTrigger, error) { - tts, err := client.V1().TimeTrigger().List(namespace) +func getAllTimeTriggers(ctx context.Context, client cmd.Client, namespace string) ([]fv1.TimeTrigger, error) { + tts, err := client.FissionClientSet.CoreV1().TimeTriggers(namespace).List(ctx, metav1.ListOptions{}) if err != nil { return nil, errors.Errorf("Unable to get Time Triggers %v", err.Error()) } - return tts, nil + return tts.Items, nil } // getAllKubeWatchTriggers get lists of Kube Watchers in all namespaces -func getAllKubeWatchTriggers(client client.Interface, namespace string) ([]fv1.KubernetesWatchTrigger, error) { - ws, err := client.V1().KubeWatcher().List(namespace) +func getAllKubeWatchTriggers(ctx context.Context, client cmd.Client, namespace string) ([]fv1.KubernetesWatchTrigger, error) { + ws, err := client.FissionClientSet.CoreV1().KubernetesWatchTriggers(namespace).List(ctx, metav1.ListOptions{}) if err != nil { return nil, errors.Errorf("Unable to get Kube Watchers %v", err.Error()) } - return ws, nil + return ws.Items, nil } diff --git a/pkg/fission-cli/cmd/spec/spec.go b/pkg/fission-cli/cmd/spec/spec.go index ce16d6fe..e3fe0766 100644 --- a/pkg/fission-cli/cmd/spec/spec.go +++ b/pkg/fission-cli/cmd/spec/spec.go @@ -31,6 +31,7 @@ import ( fv1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" + "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd/spec/types" "github.com/fission/fission/pkg/fission-cli/console" "github.com/fission/fission/pkg/fission-cli/util" @@ -297,7 +298,7 @@ func (fr *FissionResources) validateFunctionReference(functions map[string]bool, } // Validate validates the spec file for irregular references -func (fr *FissionResources) Validate(input cli.Input) ([]string, error) { +func (fr *FissionResources) Validate(input cli.Input, client cmd.Client) ([]string, error) { result := utils.MultiErrorWithFormat() var warnings []string @@ -397,25 +398,17 @@ func (fr *FissionResources) Validate(input cli.Input) ([]string, error) { } } - client, err := util.GetServer(input) - if err != nil { - return warnings, err - } for _, cm := range f.Spec.ConfigMaps { - err := client.V1().Misc().ConfigMapExists(&metav1.ObjectMeta{ - Name: cm.Name, - Namespace: cm.Namespace, - }) + + err := util.ConfigMapExists(input.Context(), &metav1.ObjectMeta{Namespace: cm.Namespace, Name: cm.Name}, client.KubernetesClient) if k8serrors.IsNotFound(err) { warnings = append(warnings, fmt.Sprintf("Configmap %s is referred in the spec but not present in the cluster", cm.Name)) } } for _, s := range f.Spec.Secrets { - err := client.V1().Misc().SecretExists(&metav1.ObjectMeta{ - Name: s.Name, - Namespace: s.Namespace, - }) + err := util.SecretExists(input.Context(), &metav1.ObjectMeta{Namespace: s.Namespace, Name: s.Name}, client.KubernetesClient) + if k8serrors.IsNotFound(err) { warnings = append(warnings, fmt.Sprintf("Secret %s is referred in the spec but not present in the cluster", s.Name)) } diff --git a/pkg/fission-cli/cmd/spec/validate.go b/pkg/fission-cli/cmd/spec/validate.go index 5b230261..049e3910 100644 --- a/pkg/fission-cli/cmd/spec/validate.go +++ b/pkg/fission-cli/cmd/spec/validate.go @@ -18,6 +18,7 @@ package spec import ( "bytes" + "context" "fmt" "os" "path/filepath" @@ -29,7 +30,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" fv1 "github.com/fission/fission/pkg/apis/core/v1" - "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/console" @@ -81,12 +81,12 @@ func (opts *ValidateSubCommand) run(input cli.Input, fr *FissionResources) (err var warnings []string // this does the rest of the checks, like dangling refs - warnings, err = fr.Validate(input) + warnings, err = fr.Validate(input, opts.Client()) if err != nil { return errors.Wrap(err, "error validating specs") } - err = resourceConflictCheck(opts.Client(), fr, input.Bool(flagkey.SpecAllowConflicts), "") + err = resourceConflictCheck(input.Context(), opts.Client(), fr, input.Bool(flagkey.SpecAllowConflicts), "") if err != nil { return errors.Wrap(err, "name conflict error") } @@ -104,11 +104,11 @@ func (opts *ValidateSubCommand) run(input cli.Input, fr *FissionResources) (err // the same name is already present in the same cluster namespace. // If a same name resource exists in the same namespace, a name // conflict error will be returned. -func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowConflicts bool, namespace string) error { +func resourceConflictCheck(ctx context.Context, c cmd.Client, fr *FissionResources, specAllowConflicts bool, namespace string) error { deployUID := fr.DeploymentConfig.UID result := utils.MultiErrorWithFormat() - fnList, err := getAllFunctions(c, namespace) + fnList, err := getAllFunctions(ctx, c, namespace) if err != nil { return errors.Errorf("Unable to get Functions %v", err.Error()) } @@ -121,7 +121,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowCo } } - envList, err := getAllEnvironments(c, namespace) + envList, err := getAllEnvironments(ctx, c, namespace) if err != nil { return errors.Errorf("Unable to get Environments %v", err.Error()) } @@ -134,7 +134,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowCo } } - pkgList, err := getAllPackages(c, namespace) + pkgList, err := getAllPackages(ctx, c, namespace) if err != nil { return errors.Errorf("Unable to get Packages %v", err.Error()) } @@ -147,7 +147,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowCo } } - httptriggerList, err := getAllHTTPTriggers(c, namespace) + httptriggerList, err := getAllHTTPTriggers(ctx, c, namespace) if err != nil { return errors.Errorf("Unable to get HTTPTrigger %v", err.Error()) } @@ -160,7 +160,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowCo } } - mqtriggerList, err := getAllMessageQueueTriggers(c, "", namespace) + mqtriggerList, err := getAllMessageQueueTriggers(ctx, c, "", namespace) if err != nil { return errors.Errorf("Unable to get Message Queue Trigger %v", err.Error()) } @@ -173,7 +173,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowCo } } - timetriggerList, err := getAllTimeTriggers(c, namespace) + timetriggerList, err := getAllTimeTriggers(ctx, c, namespace) if err != nil { return errors.Errorf("Unable to get Time Trigger %v", err.Error()) } @@ -186,7 +186,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowCo } } - kubewatchtriggerList, err := getAllKubeWatchTriggers(c, namespace) + kubewatchtriggerList, err := getAllKubeWatchTriggers(ctx, c, namespace) if err != nil { return errors.Errorf("Unable to get Kubernetes Watch Trigger %v", err.Error()) } diff --git a/pkg/fission-cli/cmd/support/dump.go b/pkg/fission-cli/cmd/support/dump.go index 8366244d..70b42de0 100644 --- a/pkg/fission-cli/cmd/support/dump.go +++ b/pkg/fission-cli/cmd/support/dump.go @@ -29,7 +29,6 @@ import ( "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/cmd/support/resources" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" "github.com/fission/fission/pkg/utils" ) @@ -51,7 +50,6 @@ func (opts *DumpSubCommand) do(input cli.Input) error { nozip := input.Bool(flagkey.SupportNoZip) outputDir := input.String(flagkey.SupportOutput) - kubeContext := input.String(flagkey.KubeContext) // check whether the dump directory exists. _, err := os.Stat(outputDir) if err != nil && os.IsNotExist(err) { @@ -68,10 +66,7 @@ func (opts *DumpSubCommand) do(input cli.Input) error { panic(errors.Wrap(err, "Error creating dump directory for dumping files")) } - _, k8sClient, err := util.GetKubernetesClient(kubeContext) - if err != nil { - return err - } + k8sClient := opts.Client().KubernetesClient ress := map[string]resources.Resource{ // kubernetes info @@ -79,7 +74,7 @@ func (opts *DumpSubCommand) do(input cli.Input) error { "kubernetes-nodes": resources.NewKubernetesObjectDumper(k8sClient, resources.KubernetesNode, ""), // fission info - "fission-version": resources.NewFissionVersion(opts.Client()), + "fission-version": resources.NewFissionVersion(opts.Client(), input), // fission component logs & spec "fission-components-svc-spec": resources.NewKubernetesObjectDumper(k8sClient, resources.KubernetesService, diff --git a/pkg/fission-cli/cmd/support/resources/crd.go b/pkg/fission-cli/cmd/support/resources/crd.go index 18e9ee34..ecc46329 100644 --- a/pkg/fission-cli/cmd/support/resources/crd.go +++ b/pkg/fission-cli/cmd/support/resources/crd.go @@ -23,7 +23,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" - "github.com/fission/fission/pkg/controller/client" + "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/console" ) @@ -39,11 +39,11 @@ const ( ) type CrdDumper struct { - client client.Interface + client cmd.Client crdType string } -func NewCrdDumper(client client.Interface, crdType string) Resource { +func NewCrdDumper(client cmd.Client, crdType string) Resource { return CrdDumper{client: client, crdType: crdType} } @@ -51,62 +51,62 @@ func (res CrdDumper) Dump(ctx context.Context, dumpDir string) { switch res.crdType { case CrdEnvironment: - items, err := res.client.V1().Environment().List(metav1.NamespaceAll) + items, err := res.client.FissionClientSet.CoreV1().Environments(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) return } - for _, item := range items { + for _, item := range items.Items { f := getFileName(dumpDir, item.ObjectMeta) writeToFile(f, item) } case CrdFunction: - items, err := res.client.V1().Function().List(metav1.NamespaceAll) + items, err := res.client.FissionClientSet.CoreV1().Functions(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) return } - for _, item := range items { + for _, item := range items.Items { f := getFileName(dumpDir, item.ObjectMeta) writeToFile(f, item) } case CrdPackage: - items, err := res.client.V1().Package().List(metav1.NamespaceAll) + items, err := res.client.FissionClientSet.CoreV1().Packages(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) return } - for _, item := range items { + for _, item := range items.Items { item = pkgClean(item) f := getFileName(dumpDir, item.ObjectMeta) writeToFile(f, item) } case CrdHttpTrigger: - items, err := res.client.V1().HTTPTrigger().List(metav1.NamespaceAll) + items, err := res.client.FissionClientSet.CoreV1().HTTPTriggers(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) return } - for _, item := range items { + for _, item := range items.Items { f := getFileName(dumpDir, item.ObjectMeta) writeToFile(f, item) } case CrdKubeWatcher: - items, err := res.client.V1().KubeWatcher().List(metav1.NamespaceAll) + items, err := res.client.FissionClientSet.CoreV1().KubernetesWatchTriggers(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) return } - for _, item := range items { + for _, item := range items.Items { f := getFileName(dumpDir, item.ObjectMeta) writeToFile(f, item) } @@ -114,14 +114,12 @@ func (res CrdDumper) Dump(ctx context.Context, dumpDir string) { case CrdMessageQueueTrigger: var triggers []fv1.MessageQueueTrigger - for _, mqType := range []string{fv1.MessageQueueTypeKafka} { - l, err := res.client.V1().MessageQueueTrigger().List(mqType, metav1.NamespaceAll) - if err != nil { - console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) - break - } - triggers = append(triggers, l...) + l, err := res.client.FissionClientSet.CoreV1().MessageQueueTriggers(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) + if err != nil { + console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) + break } + triggers = append(triggers, l.Items...) for _, item := range triggers { f := getFileName(dumpDir, item.ObjectMeta) @@ -129,13 +127,13 @@ func (res CrdDumper) Dump(ctx context.Context, dumpDir string) { } case CrdTimeTrigger: - items, err := res.client.V1().TimeTrigger().List(metav1.NamespaceAll) + items, err := res.client.FissionClientSet.CoreV1().TimeTriggers(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { console.Warn(fmt.Sprintf("Error getting %v list: %v", res.crdType, err)) return } - for _, item := range items { + for _, item := range items.Items { f := getFileName(dumpDir, item.ObjectMeta) writeToFile(f, item) } diff --git a/pkg/fission-cli/cmd/support/resources/fissionversion.go b/pkg/fission-cli/cmd/support/resources/fissionversion.go index 5e162d04..0334f9ed 100644 --- a/pkg/fission-cli/cmd/support/resources/fissionversion.go +++ b/pkg/fission-cli/cmd/support/resources/fissionversion.go @@ -21,20 +21,22 @@ import ( "fmt" "path/filepath" - "github.com/fission/fission/pkg/controller/client" + "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" + "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/util" ) type FissionVersion struct { - client client.Interface + client cmd.Client + input cli.Input } -func NewFissionVersion(client client.Interface) Resource { - return FissionVersion{client: client} +func NewFissionVersion(client cmd.Client, input cli.Input) Resource { + return FissionVersion{client: client, input: input} } func (res FissionVersion) Dump(ctx context.Context, dumpDir string) { - ver := util.GetVersion(ctx, res.client) + ver := util.GetVersion(ctx, res.input, res.client) file := filepath.Clean(fmt.Sprintf("%v/%v", dumpDir, "fission-version.txt")) writeToFile(file, ver) } diff --git a/pkg/fission-cli/cmd/timetrigger/create.go b/pkg/fission-cli/cmd/timetrigger/create.go index e12dd340..17f85fa9 100644 --- a/pkg/fission-cli/cmd/timetrigger/create.go +++ b/pkg/fission-cli/cmd/timetrigger/create.go @@ -28,7 +28,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fv1 "github.com/fission/fission/pkg/apis/core/v1" - "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd/spec" "github.com/fission/fission/pkg/fission-cli/console" @@ -68,7 +67,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) (err error) { return errors.New("Need a function name to create a trigger, use --function") } - userProvidedNS, fnNamespace, err := util.GetResourceNamespace(input, flagkey.NamespaceFunction) + userProvidedNS, fnNamespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceFunction) if err != nil { return errors.Wrap(err, "error in deleting function ") } @@ -143,17 +142,14 @@ func (opts *CreateSubCommand) run(input cli.Input) error { return nil } - _, err := opts.Client().V1().TimeTrigger().Create(opts.trigger) + _, err := opts.Client().FissionClientSet.CoreV1().TimeTriggers(opts.trigger.Namespace).Create(input.Context(), opts.trigger, metav1.CreateOptions{}) if err != nil { return errors.Wrap(err, "error creating Time trigger") } fmt.Printf("trigger '%v' created\n", opts.trigger.ObjectMeta.Name) - t, err := getAPITimeInfo(opts.Client()) - if err != nil { - return err - } + t := util.GetServerInfo(input, opts.Client()).ServerTime.CurrentTime.UTC() err = getCronNextNActivationTime(opts.trigger.Spec.Cron, t, 1) if err != nil { @@ -163,14 +159,6 @@ func (opts *CreateSubCommand) run(input cli.Input) error { return nil } -func getAPITimeInfo(client client.Interface) (time.Time, error) { - serverInfo, err := client.V1().Misc().ServerInfo() - if err != nil { - return time.Time{}, errors.Errorf("Error syncing server time information: %v", err) - } - return serverInfo.ServerTime.CurrentTime, nil -} - func getCronNextNActivationTime(cronSpec string, serverTime time.Time, round int) error { sched, err := cron.Parse(cronSpec) if err != nil { diff --git a/pkg/fission-cli/cmd/timetrigger/delete.go b/pkg/fission-cli/cmd/timetrigger/delete.go index 3eb1eb35..742ed438 100644 --- a/pkg/fission-cli/cmd/timetrigger/delete.go +++ b/pkg/fission-cli/cmd/timetrigger/delete.go @@ -20,12 +20,12 @@ import ( "fmt" "github.com/pkg/errors" + kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type DeleteSubCommand struct { @@ -38,23 +38,19 @@ func Delete(input cli.Input) error { func (opts *DeleteSubCommand) do(input cli.Input) (err error) { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceTrigger) if err != nil { return errors.Wrap(err, "error in deleting function ") } - m := &metav1.ObjectMeta{ - Name: input.String(flagkey.TtName), - Namespace: namespace, - } - err = opts.Client().V1().TimeTrigger().Delete(m) + err = opts.Client().FissionClientSet.CoreV1().TimeTriggers(namespace).Delete(input.Context(), input.String(flagkey.TtName), metav1.DeleteOptions{}) if err != nil { - if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) { + if input.Bool(flagkey.IgnoreNotFound) && kerrors.IsNotFound(err) { return nil } return errors.Wrap(err, "error deleting trigger") } - fmt.Printf("trigger '%v' deleted\n", m.Name) + fmt.Printf("trigger '%v' deleted\n", input.String(flagkey.TtName)) return nil } diff --git a/pkg/fission-cli/cmd/timetrigger/list.go b/pkg/fission-cli/cmd/timetrigger/list.go index 7b96340c..05001308 100644 --- a/pkg/fission-cli/cmd/timetrigger/list.go +++ b/pkg/fission-cli/cmd/timetrigger/list.go @@ -22,12 +22,11 @@ import ( "text/tabwriter" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" - "github.com/fission/fission/pkg/fission-cli/util" ) type ListSubCommand struct { @@ -39,17 +38,15 @@ func List(input cli.Input) error { } func (opts *ListSubCommand) do(input cli.Input) (err error) { - _, ttNs, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + _, ttNs, err := opts.GetResourceNamespace(input, flagkey.NamespaceTrigger) if err != nil { return errors.Wrap(err, "error in deleting function ") } - var tts []v1.TimeTrigger if input.Bool(flagkey.AllNamespaces) { - tts, err = opts.Client().V1().TimeTrigger().List("") - } else { - tts, err = opts.Client().V1().TimeTrigger().List(ttNs) + ttNs = metav1.NamespaceAll } + tts, err := opts.Client().FissionClientSet.CoreV1().TimeTriggers(ttNs).List(input.Context(), metav1.ListOptions{}) if err != nil { return errors.Wrap(err, "list Time triggers") @@ -58,7 +55,7 @@ func (opts *ListSubCommand) do(input cli.Input) (err error) { w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) fmt.Fprintf(w, "%v\t%v\t%v\n", "NAME", "CRON", "FUNCTION_NAME") - for _, tt := range tts { + for _, tt := range tts.Items { fmt.Fprintf(w, "%v\t%v\t%v\n", tt.ObjectMeta.Name, tt.Spec.Cron, tt.Spec.FunctionReference.Name) } diff --git a/pkg/fission-cli/cmd/timetrigger/test.go b/pkg/fission-cli/cmd/timetrigger/test.go index e9365370..cd30e77e 100644 --- a/pkg/fission-cli/cmd/timetrigger/test.go +++ b/pkg/fission-cli/cmd/timetrigger/test.go @@ -22,6 +22,7 @@ import ( "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" "github.com/fission/fission/pkg/fission-cli/cmd" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" + "github.com/fission/fission/pkg/fission-cli/util" ) type ShowSubCommand struct { @@ -44,12 +45,9 @@ func (opts *ShowSubCommand) run(flaginput cli.Input) error { return errors.New("need a cron spec like '0 30 * * * *', '@every 1h30m', or '@hourly'; use --cron") } - t, err := getAPITimeInfo(opts.Client()) - if err != nil { - return err - } + t := util.GetServerInfo(flaginput, opts.Client()).ServerTime.CurrentTime.UTC() - err = getCronNextNActivationTime(cronSpec, t, round) + err := getCronNextNActivationTime(cronSpec, t, round) if err != nil { return errors.Wrap(err, "error passing cron spec examination") } diff --git a/pkg/fission-cli/cmd/timetrigger/update.go b/pkg/fission-cli/cmd/timetrigger/update.go index 8a6ac466..d2f0832d 100644 --- a/pkg/fission-cli/cmd/timetrigger/update.go +++ b/pkg/fission-cli/cmd/timetrigger/update.go @@ -48,14 +48,12 @@ func (opts *UpdateSubCommand) do(input cli.Input) error { } func (opts *UpdateSubCommand) complete(input cli.Input) error { - _, namespace, err := util.GetResourceNamespace(input, flagkey.NamespaceTrigger) + _, namespace, err := opts.GetResourceNamespace(input, flagkey.NamespaceTrigger) if err != nil { return errors.Wrap(err, "error in deleting function ") } - tt, err := opts.Client().V1().TimeTrigger().Get(&metav1.ObjectMeta{ - Name: input.String(flagkey.TtName), - Namespace: namespace, - }) + + tt, err := opts.Client().FissionClientSet.CoreV1().TimeTriggers(namespace).Get(input.Context(), input.String(flagkey.TtName), metav1.GetOptions{}) if err != nil { return errors.Wrap(err, "error getting time trigger") } @@ -70,7 +68,7 @@ func (opts *UpdateSubCommand) complete(input cli.Input) error { fnName := input.String("function") if len(fnName) > 0 { functionList := []string{fnName} - err := util.CheckFunctionExistence(opts.Client(), functionList, namespace) + err := util.CheckFunctionExistence(input.Context(), opts.Client(), functionList, namespace) if err != nil { console.Warn(err.Error()) } @@ -88,14 +86,14 @@ func (opts *UpdateSubCommand) complete(input cli.Input) error { } func (opts *UpdateSubCommand) run(input cli.Input) error { - _, err := opts.Client().V1().TimeTrigger().Update(opts.trigger) + _, err := opts.Client().FissionClientSet.CoreV1().TimeTriggers(opts.trigger.ObjectMeta.Namespace).Update(input.Context(), opts.trigger, metav1.UpdateOptions{}) if err != nil { return errors.Wrap(err, "error updating Time trigger") } fmt.Printf("trigger '%v' updated\n", opts.trigger.ObjectMeta.Name) - t, err := getAPITimeInfo(opts.Client()) + t := util.GetServerInfo(input, opts.Client()).ServerTime.CurrentTime.UTC() if err != nil { return err } diff --git a/pkg/fission-cli/cmd/token/create.go b/pkg/fission-cli/cmd/token/create.go index 669cb77f..c08e04cd 100644 --- a/pkg/fission-cli/cmd/token/create.go +++ b/pkg/fission-cli/cmd/token/create.go @@ -64,9 +64,8 @@ func (opts *CreateSubCommand) run(input cli.Input) error { jsonValue, _ := json.Marshal(values) - kubeContext := input.String(flagkey.KubeContext) // Portforward to the fission router - localRouterPort, err := util.SetupPortForward(input.Context(), util.GetFissionNamespace(), "application=fission-router", kubeContext) + localRouterPort, err := util.SetupPortForward(input.Context(), opts.Client(), util.GetFissionNamespace(), "application=fission-router") if err != nil { return err } diff --git a/pkg/fission-cli/cmd/version/version.go b/pkg/fission-cli/cmd/version/version.go index cb1ef9a3..14b781dc 100644 --- a/pkg/fission-cli/cmd/version/version.go +++ b/pkg/fission-cli/cmd/version/version.go @@ -36,7 +36,7 @@ func Version(input cli.Input) error { } func (opts *VersionSubCommand) do(input cli.Input) error { - ver := util.GetVersion(input.Context(), opts.Client()) + ver := util.GetVersion(input.Context(), input, opts.Client()) bs, err := yaml.Marshal(ver) if err != nil { return errors.Wrap(err, "error formatting versions") diff --git a/pkg/fission-cli/util/portforward.go b/pkg/fission-cli/util/portforward.go index b87029c2..335f775f 100644 --- a/pkg/fission-cli/util/portforward.go +++ b/pkg/fission-cli/util/portforward.go @@ -32,6 +32,7 @@ import ( "k8s.io/client-go/tools/portforward" "k8s.io/client-go/transport/spdy" + "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/console" "github.com/fission/fission/pkg/utils" ) @@ -43,7 +44,7 @@ const maxDuration time.Duration = 2000 // is found by looking for a service in the same namespace and using // its targetPort. Once the port forward is started, wait for it to // start accepting connections before returning. -func SetupPortForward(ctx context.Context, namespace, labelSelector string, kubeContext string) (string, error) { +func SetupPortForward(ctx context.Context, client cmd.Client, namespace, labelSelector string) (string, error) { console.Verbose(2, "Setting up port forward to %s in namespace %s", labelSelector, namespace) @@ -71,7 +72,7 @@ func SetupPortForward(ctx context.Context, namespace, labelSelector string, kube console.Verbose(2, "Starting port forward from local port %v", localPort) - readyC, _, err := runPortForward(ctx, labelSelector, localPort, namespace, kubeContext) + readyC, _, err := runPortForward(ctx, client, labelSelector, localPort, namespace) if err != nil { fmt.Printf("Error forwarding to port %v: %s", localPort, err.Error()) return "", err @@ -119,11 +120,7 @@ func findFreePort() (string, error) { } // runPortForward creates a local port forward to the specified pod -func runPortForward(ctx context.Context, labelSelector string, localPort string, ns string, kubeContext string) (chan struct{}, chan struct{}, error) { - config, clientset, err := GetKubernetesClient(kubeContext) - if err != nil { - return nil, nil, err - } +func runPortForward(ctx context.Context, client cmd.Client, labelSelector string, localPort string, ns string) (chan struct{}, chan struct{}, error) { console.Verbose(2, "Connected to Kubernetes API") @@ -133,7 +130,7 @@ func runPortForward(ctx context.Context, labelSelector string, localPort string, } // get the pod; if there is more than one, ask the user to disambiguate - podList, err := clientset.CoreV1().Pods(ns). + podList, err := client.KubernetesClient.CoreV1().Pods(ns). List(ctx, metav1.ListOptions{LabelSelector: labelSelector}) if err != nil { return nil, nil, errors.Wrapf(err, "error getting pod for port-forwarding with label selector %v", labelSelector) @@ -179,7 +176,7 @@ func runPortForward(ctx context.Context, labelSelector string, localPort string, } // get the service and the target port - svcs, err := clientset.CoreV1().Services(podNameSpace). + svcs, err := client.KubernetesClient.CoreV1().Services(podNameSpace). List(ctx, metav1.ListOptions{LabelSelector: labelSelector}) if err != nil { return nil, nil, errors.Wrapf(err, "Error getting %v service", labelSelector) @@ -199,7 +196,7 @@ func runPortForward(ctx context.Context, labelSelector string, localPort string, readyChannel := make(chan struct{}) // create request URL - req := clientset.CoreV1().RESTClient().Post().Resource("pods"). + req := client.KubernetesClient.CoreV1().RESTClient().Post().Resource("pods"). Namespace(podNameSpace).Name(podName).SubResource("portforward") url := req.URL() @@ -208,7 +205,7 @@ func runPortForward(ctx context.Context, labelSelector string, localPort string, ports := []string{portCombo} // actually start the port-forwarding process here - transport, upgrader, err := spdy.RoundTripperFor(config) + transport, upgrader, err := spdy.RoundTripperFor(client.RestConfig) if err != nil { return nil, nil, errors.Errorf("Failed to connect to Fission service on Kubernetes") } diff --git a/pkg/fission-cli/util/util.go b/pkg/fission-cli/util/util.go index 1215c557..a3577cc8 100644 --- a/pkg/fission-cli/util/util.go +++ b/pkg/fission-cli/util/util.go @@ -19,11 +19,12 @@ package util import ( "context" "fmt" + "io" "net/url" "os" - "os/user" "path/filepath" "regexp" + "sort" "strconv" "strings" @@ -36,12 +37,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" + fv1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/controller/client" "github.com/fission/fission/pkg/controller/client/rest" "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" + "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/console" flagkey "github.com/fission/fission/pkg/fission-cli/flag/key" "github.com/fission/fission/pkg/info" @@ -54,13 +55,13 @@ func GetFissionNamespace() string { return fissionNamespace } -func GetApplicationUrl(ctx context.Context, selector string, kubeContext string) (string, error) { +func GetApplicationUrl(ctx context.Context, client cmd.Client, selector string) (string, error) { var serverUrl string // Use FISSION_URL env variable if set; otherwise, port-forward to controller. fissionUrl := os.Getenv("FISSION_URL") if len(fissionUrl) == 0 { fissionNamespace := GetFissionNamespace() - localPort, err := SetupPortForward(ctx, fissionNamespace, selector, kubeContext) + localPort, err := SetupPortForward(ctx, client, fissionNamespace, selector) if err != nil { return "", err } @@ -104,87 +105,11 @@ func KubifyName(old string) string { return newName } -func getLoadingRules() (loadingRules *clientcmd.ClientConfigLoadingRules, err error) { - loadingRules = clientcmd.NewDefaultClientConfigLoadingRules() - - kubeConfigPath := os.Getenv("KUBECONFIG") - if len(kubeConfigPath) == 0 { - var homeDir string - usr, err := user.Current() - if err != nil { - // In case that user.Current() may be unable to work under some circumstances and return errors like - // "user: Current not implemented on darwin/amd64" due to cross-compilation problem. (https://github.com/golang/go/issues/6376). - // Instead of doing fatal here, we fallback to get home directory from the environment $HOME. - console.Warn(fmt.Sprintf("Could not get the current user's directory (%s), fallback to get it from env $HOME", err)) - homeDir = os.Getenv("HOME") - } else { - homeDir = usr.HomeDir - } - kubeConfigPath = filepath.Join(homeDir, ".kube", "config") - - if _, err := os.Stat(kubeConfigPath); os.IsNotExist(err) { - return nil, errors.New("Couldn't find kubeconfig file. " + - "Set the KUBECONFIG environment variable to your kubeconfig's path.") - } - loadingRules.ExplicitPath = kubeConfigPath - console.Verbose(2, "Using kubeconfig from %q", kubeConfigPath) - } else { - console.Verbose(2, "Using kubeconfig from environment %q", kubeConfigPath) - } - return loadingRules, nil -} - -// GetKubernetesClient builds a new kubernetes client. If the KUBECONFIG -// environment variable is empty or doesn't exist, ~/.kube/config is used for -// the kube config path -func GetKubernetesClient(kubeContext string) (*restclient.Config, kubernetes.Interface, error) { - loadingRules, err := getLoadingRules() - if err != nil { - return nil, nil, err - } - - config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( - loadingRules, &clientcmd.ConfigOverrides{CurrentContext: kubeContext}).ClientConfig() - if err != nil { - return nil, nil, errors.Wrap(err, "Failed to build Kubernetes config") - } - - clientset, err := kubernetes.NewForConfig(config) - if err != nil { - return nil, nil, errors.Wrap(err, "Failed to connect to Kubernetes") - } - - return config, clientset, nil -} - -// GetKubernetesNamespace builds a new kubernetes client. If the KUBECONFIG -// environment variable is empty or doesn't exist, ~/.kube/config is used for -// the kube config path -func GetKubernetesNamespace(kubeContext string) (currentNS string, err error) { - loadingRules, err := getLoadingRules() - if err != nil { - return "", err - } - - namespace, _, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( - loadingRules, &clientcmd.ConfigOverrides{CurrentContext: kubeContext}).Namespace() - if err != nil { - return "", errors.Wrap(err, "Failed to build Kubernetes config") - } - - return namespace, nil -} - // given a list of functions, this checks if the functions actually exist on the cluster -func CheckFunctionExistence(client client.Interface, functions []string, fnNamespace string) (err error) { +func CheckFunctionExistence(ctx context.Context, client cmd.Client, functions []string, fnNamespace string) (err error) { fnMissing := make([]string, 0) for _, fnName := range functions { - meta := &metav1.ObjectMeta{ - Name: fnName, - Namespace: fnNamespace, - } - - _, err := client.V1().Function().Get(meta) + _, err := client.FissionClientSet.CoreV1().Functions(fnNamespace).Get(ctx, fnName, metav1.GetOptions{}) if err != nil { fnMissing = append(fnMissing, fnName) } @@ -197,7 +122,7 @@ func CheckFunctionExistence(client client.Interface, functions []string, fnNames return nil } -func GetVersion(ctx context.Context, client client.Interface) info.Versions { +func GetVersion(ctx context.Context, input cli.Input, cmdClient cmd.Client) info.Versions { // Fetch client versions versions := info.Versions{ Client: map[string]info.BuildMeta{ @@ -211,11 +136,7 @@ func GetVersion(ctx context.Context, client client.Interface) info.Versions { } } - serverInfo, err := client.V1().Misc().ServerInfo() - if err != nil { - console.Warn(fmt.Sprintf("Error getting Fission API version: %v", err)) - serverInfo = &info.ServerInfo{} - } + serverInfo := GetServerInfo(input, cmdClient) // Fetch server versions versions.Server = map[string]info.BuildMeta{ @@ -227,20 +148,28 @@ func GetVersion(ctx context.Context, client client.Interface) info.Versions { return versions } -func GetServer(input cli.Input) (c client.Interface, err error) { - serverUrl, err := GetServerURL(input) +func GetServerInfo(input cli.Input, cmdClient cmd.Client) *info.ServerInfo { + serverUrl, err := GetServerURL(input, cmdClient) if err != nil { - return nil, err + return &info.ServerInfo{} } - return client.MakeClientset(rest.NewRESTClient(serverUrl)), nil + restClient := rest.NewRESTClient(serverUrl) + client := client.MakeClientset(restClient) + + serverInfo, err := client.V1().Misc().ServerInfo() + if err != nil { + console.Warn(fmt.Sprintf("Error getting Fission API version: %v", err)) + serverInfo = &info.ServerInfo{} + } + + return serverInfo } -func GetServerURL(input cli.Input) (serverUrl string, err error) { +func GetServerURL(input cli.Input, client cmd.Client) (serverUrl string, err error) { serverUrl = input.GlobalString(flagkey.Server) - kubeContext := input.String(flagkey.KubeContext) if len(serverUrl) == 0 { // starts local portforwarder etc. - serverUrl, err = GetApplicationUrl(input.Context(), "application=fission-api", kubeContext) + serverUrl, err = GetApplicationUrl(input.Context(), client, "application=fission-api") if err != nil { return "", err } @@ -472,8 +401,8 @@ func ApplyLabelsAndAnnotations(input cli.Input, objectMeta *metav1.ObjectMeta) e return nil } -func GetStorageURL(ctx context.Context, kubeContext string) (*url.URL, error) { - storageLocalPort, err := SetupPortForward(ctx, GetFissionNamespace(), "application=fission-storage", kubeContext) +func GetStorageURL(ctx context.Context, client cmd.Client) (*url.URL, error) { + storageLocalPort, err := SetupPortForward(ctx, client, GetFissionNamespace(), "application=fission-storage") if err != nil { return nil, err } @@ -486,30 +415,151 @@ func GetStorageURL(ctx context.Context, kubeContext string) (*url.URL, error) { return serverURL, nil } -func GetResourceNamespace(input cli.Input, deprecatedFlag string) (namespace, currentNS string, err error) { - namespace = input.String(deprecatedFlag) - currentNS = namespace - - if input.String(flagkey.Namespace) != "" { - namespace = input.String(flagkey.Namespace) - currentNS = namespace - console.Verbose(2, "Namespace for resource %s ", currentNS) - return namespace, currentNS, err +// CheckHTTPTriggerDuplicates checks whether the tuple (Method, Host, URL) is duplicate or not. +func CheckHTTPTriggerDuplicates(ctx context.Context, client cmd.Client, t *fv1.HTTPTrigger) error { + triggers, err := client.FissionClientSet.CoreV1().HTTPTriggers(metav1.NamespaceAll).List(ctx, metav1.ListOptions{}) + if err != nil { + return err } - - if namespace == "" { - if os.Getenv("FISSION_DEFAULT_NAMESPACE") != "" { - currentNS = os.Getenv("FISSION_DEFAULT_NAMESPACE") - } else { - kubeContext := input.String(flagkey.KubeContext) - currentNS, err = GetKubernetesNamespace(kubeContext) - if err != nil { - return namespace, currentNS, err + for _, ht := range triggers.Items { + if ht.ObjectMeta.UID == t.ObjectMeta.UID { + // Same resource. No need to check. + continue + } + urlMatch := false + if (ht.Spec.RelativeURL != "" && ht.Spec.RelativeURL == t.Spec.RelativeURL) || (ht.Spec.Prefix != nil && t.Spec.Prefix != nil && *ht.Spec.Prefix != "" && *ht.Spec.Prefix == *t.Spec.Prefix) { + urlMatch = true + } + methodMatch := false + if ht.Spec.Method == t.Spec.Method && len(ht.Spec.Methods) == len(t.Spec.Methods) { + methodMatch = true + sort.Strings(ht.Spec.Methods) + sort.Strings(t.Spec.Methods) + for i, m1 := range ht.Spec.Methods { + if m1 != t.Spec.Methods[i] { + methodMatch = false + } } } + if urlMatch && methodMatch && ht.Spec.Method == t.Spec.Method && ht.Spec.Host == t.Spec.Host { + return fmt.Errorf("HTTPTrigger with same Host, URL & method already exists (%v)", + ht.ObjectMeta.Name) + } + } + return nil +} + +func SecretExists(ctx context.Context, m *metav1.ObjectMeta, kClient kubernetes.Interface) error { + + _, err := kClient.CoreV1().Secrets(m.Namespace).Get(ctx, m.Name, metav1.GetOptions{}) + return err +} + +func ConfigMapExists(ctx context.Context, m *metav1.ObjectMeta, kClient kubernetes.Interface) error { + + _, err := kClient.CoreV1().ConfigMaps(m.Namespace).Get(ctx, m.Name, metav1.GetOptions{}) + return err +} + +func GetSvcName(ctx context.Context, kClient kubernetes.Interface, application string) (string, error) { + var podNamespace = os.Getenv("POD_NAMESPACE") + if podNamespace == "" { + podNamespace = "fission" } - console.Verbose(2, "Namespace for resource %s ", currentNS) + appLabelSelector := "application=" + application - return namespace, currentNS, nil + services, err := kClient.CoreV1().Services(podNamespace).List(ctx, metav1.ListOptions{ + LabelSelector: appLabelSelector, + }) + if err != nil { + return "", err + } + + if len(services.Items) > 1 || len(services.Items) == 0 { + return "", errors.Errorf("more than one service found for application=%s", application) + } + service := services.Items[0] + return service.Name + "." + podNamespace, nil +} + +// FunctionPodLogs : Get logs for a function directly from pod +func FunctionPodLogs(ctx context.Context, fnName, ns string, client cmd.Client) (err error) { + + podNs := "fission-function" + + if len(ns) == 0 { + ns = metav1.NamespaceDefault + } else if ns != metav1.NamespaceDefault { + podNs = ns + } + + f, err := client.FissionClientSet.CoreV1().Functions(ns).Get(ctx, fnName, metav1.GetOptions{}) + if err != nil { + return err + } + + // Get function Pods first + selector := map[string]string{ + fv1.FUNCTION_UID: string(f.ObjectMeta.UID), + fv1.ENVIRONMENT_NAME: f.Spec.Environment.Name, + fv1.ENVIRONMENT_NAMESPACE: f.Spec.Environment.Namespace, + } + podList, err := client.KubernetesClient.CoreV1().Pods(podNs).List(ctx, metav1.ListOptions{ + LabelSelector: labels.Set(selector).AsSelector().String(), + }) + if err != nil { + return err + } + + // Get the logs for last Pod executed + pods := podList.Items + sort.Slice(pods, func(i, j int) bool { + rv1, _ := strconv.ParseInt(pods[i].ObjectMeta.ResourceVersion, 10, 32) + rv2, _ := strconv.ParseInt(pods[j].ObjectMeta.ResourceVersion, 10, 32) + return rv1 > rv2 + }) + + if len(pods) <= 0 { + return errors.New("no active pods found") + + } + + // get the pod with highest resource version + err = getContainerLog(ctx, client.KubernetesClient, f, &pods[0]) + if err != nil { + return errors.Wrapf(err, "error getting container logs") + + } + return err +} + +func getContainerLog(ctx context.Context, kubernetesClient kubernetes.Interface, fn *fv1.Function, pod *v1.Pod) (err error) { + seq := strings.Repeat("=", 35) + + for _, container := range pod.Spec.Containers { + podLogOpts := v1.PodLogOptions{Container: container.Name} // Only the env container, not fetcher + podLogsReq := kubernetesClient.CoreV1().Pods(pod.Namespace).GetLogs(pod.ObjectMeta.Name, &podLogOpts) + + podLogs, err := podLogsReq.Stream(ctx) + if err != nil { + return errors.Wrapf(err, "error streaming pod log") + } + + msg := fmt.Sprintf("\n%v\nFunction: %v\nEnvironment: %v\nNamespace: %v\nPod: %v\nContainer: %v\nNode: %v\n%v\n", seq, + fn.ObjectMeta.Name, fn.Spec.Environment.Name, pod.Namespace, pod.Name, container.Name, pod.Spec.NodeName, seq) + + if _, err := io.WriteString(os.Stdout, msg); err != nil { + return errors.Wrapf(err, "error copying pod log") + } + + _, err = io.Copy(os.Stdout, podLogs) + if err != nil { + return errors.Wrapf(err, "error copying pod log") + } + + podLogs.Close() + } + + return nil } diff --git a/pkg/fission-cli/util/util_test.go b/pkg/fission-cli/util/util_test.go index dedf0e78..cb510a3e 100644 --- a/pkg/fission-cli/util/util_test.go +++ b/pkg/fission-cli/util/util_test.go @@ -65,10 +65,10 @@ func TestGetEnvVarFromStringSlice(t *testing.T) { } } -func TestGetConfig(t *testing.T) { - response, err := GetKubernetesNamespace("") - if err != nil { - t.Log(err) - } - t.Log("Current NS: ", response) -} +// func TestGetConfig(t *testing.T) { +// response, err := GetKubernetesNamespace("") +// if err != nil { +// t.Log(err) +// } +// t.Log("Current NS: ", response) +// } diff --git a/pkg/healthcheck/healthcheck.go b/pkg/healthcheck/healthcheck.go index 72f2a7f0..231bd3ca 100644 --- a/pkg/healthcheck/healthcheck.go +++ b/pkg/healthcheck/healthcheck.go @@ -24,7 +24,8 @@ import ( "k8s.io/client-go/kubernetes" fv1 "github.com/fission/fission/pkg/apis/core/v1" - "github.com/fission/fission/pkg/controller/client" + "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" + "github.com/fission/fission/pkg/fission-cli/cmd" "github.com/fission/fission/pkg/fission-cli/util" ) @@ -50,18 +51,11 @@ type Category struct { type Checker struct { successMsg string - check func(ctx context.Context) error -} - -type Options struct { - KubeContext string - FissionClient client.Interface + check func(ctx context.Context, input cli.Input, client cmd.Client) error } type HealthChecker struct { - categories []*Category - *Options - + categories []*Category kubeAPI kubernetes.Interface fissionNamespace string } @@ -120,8 +114,8 @@ func (hc *HealthChecker) CheckServiceStatus(ctx context.Context, namespace strin return nil } -func (hc *HealthChecker) CheckFissionVersion(ctx context.Context) error { - ver := util.GetVersion(ctx, hc.FissionClient) +func (hc *HealthChecker) CheckFissionVersion(ctx context.Context, input cli.Input, client cmd.Client) error { + ver := util.GetVersion(ctx, input, client) clientVersion := ver.Client["fission/core"].Version serverVersion := ver.Server["fission/core"].Version @@ -148,7 +142,7 @@ func (hc *HealthChecker) allCategories() []*Category { []Checker{ { successMsg: "kubernetes version is compatible", - check: func(ctx context.Context) (err error) { + check: func(ctx context.Context, input cli.Input, client cmd.Client) (err error) { return hc.CheckKubeVersion() }, }, @@ -160,25 +154,25 @@ func (hc *HealthChecker) allCategories() []*Category { []Checker{ { successMsg: "controller is running fine", - check: func(ctx context.Context) error { + check: func(ctx context.Context, input cli.Input, client cmd.Client) error { return hc.CheckServiceStatus(ctx, hc.fissionNamespace, "controller") }, }, { successMsg: "executor is running fine", - check: func(ctx context.Context) error { + check: func(ctx context.Context, input cli.Input, client cmd.Client) error { return hc.CheckServiceStatus(ctx, hc.fissionNamespace, "executor") }, }, { successMsg: "router is running fine", - check: func(ctx context.Context) error { + check: func(ctx context.Context, input cli.Input, client cmd.Client) error { return hc.CheckServiceStatus(ctx, hc.fissionNamespace, "router") }, }, { successMsg: "storagesvc is running fine", - check: func(ctx context.Context) error { + check: func(ctx context.Context, input cli.Input, client cmd.Client) error { return hc.CheckServiceStatus(ctx, hc.fissionNamespace, "storagesvc") }, }, @@ -190,8 +184,8 @@ func (hc *HealthChecker) allCategories() []*Category { []Checker{ { successMsg: "fission is up-to-date", - check: func(ctx context.Context) error { - return hc.CheckFissionVersion(ctx) + check: func(ctx context.Context, input cli.Input, client cmd.Client) error { + return hc.CheckFissionVersion(ctx, input, client) }, }, }, @@ -200,15 +194,12 @@ func (hc *HealthChecker) allCategories() []*Category { } } -func NewHealthChecker(categoryIDs []CategoryID, options *Options) *HealthChecker { +func NewHealthChecker(cmd cmd.Client, categoryIDs []CategoryID) *HealthChecker { hc := &HealthChecker{ - Options: options, + kubeAPI: cmd.KubernetesClient, + fissionNamespace: "fission", } - _, clientset, _ := util.GetKubernetesClient(hc.KubeContext) - hc.kubeAPI = clientset - hc.fissionNamespace = "fission" - hc.categories = hc.allCategories() checkMap := map[CategoryID]struct{}{} @@ -224,13 +215,13 @@ func NewHealthChecker(categoryIDs []CategoryID, options *Options) *HealthChecker return hc } -func RunChecks(ctx context.Context, hc *HealthChecker) { +func RunChecks(ctx context.Context, input cli.Input, client cmd.Client, hc *HealthChecker) { for _, c := range hc.categories { if c.enabled { fmt.Println(c.ID) fmt.Println(strings.Repeat("-", 20)) for _, checker := range c.checkers { - err := checker.check(ctx) + err := checker.check(ctx, input, client) if err != nil { fmt.Printf("%s %s\n", failStatus, err) } else { diff --git a/pkg/storagesvc/client/client.go b/pkg/storagesvc/client/client.go index 417c0f09..3eff1c4d 100644 --- a/pkg/storagesvc/client/client.go +++ b/pkg/storagesvc/client/client.go @@ -185,6 +185,21 @@ func (c *Client) Download(ctx context.Context, id string, filePath string) error return nil } +// Download fetches the file identified by ID to the local file path. +// filePath must not exist. +func (c *Client) GetFile(ctx context.Context, id string) (resp *http.Response, err error) { + // url for id + url := c.GetUrl(id) + + // make request + resp, err = ctxhttp.Get(ctx, c.httpClient, url) + if err != nil { + return resp, err + } + + return resp, err +} + func (c *Client) Delete(ctx context.Context, id string) error { url := c.GetUrl(id) diff --git a/pkg/utils/otel/log.go b/pkg/utils/otel/log.go index 50c11444..2517facf 100644 --- a/pkg/utils/otel/log.go +++ b/pkg/utils/otel/log.go @@ -22,8 +22,8 @@ import ( "go.uber.org/zap" ) -func LoggerWithTraceID(context context.Context, logger *zap.Logger) *zap.Logger { - if span := trace.SpanContextFromContext(context); span.TraceID().IsValid() { +func LoggerWithTraceID(ctx context.Context, logger *zap.Logger) *zap.Logger { + if span := trace.SpanContextFromContext(ctx); span.TraceID().IsValid() { return logger.With(zap.String("trace_id", span.TraceID().String())) } return logger