feature: Added command to list pods managed by fission for environment/function (#2207)
This commit is contained in:
@@ -125,6 +125,7 @@ const (
|
|||||||
FUNCTION_UID = "functionUid"
|
FUNCTION_UID = "functionUid"
|
||||||
FUNCTION_RESOURCE_VERSION = "functionResourceVersion"
|
FUNCTION_RESOURCE_VERSION = "functionResourceVersion"
|
||||||
EXECUTOR_TYPE = "executorType"
|
EXECUTOR_TYPE = "executorType"
|
||||||
|
MANAGED = "managed"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -214,6 +214,7 @@ func (api *API) GetHandler() http.Handler {
|
|||||||
r.HandleFunc("/v2/functions/{function}", api.FunctionApiGet).Methods("GET")
|
r.HandleFunc("/v2/functions/{function}", api.FunctionApiGet).Methods("GET")
|
||||||
r.HandleFunc("/v2/functions/{function}", api.FunctionApiUpdate).Methods("PUT")
|
r.HandleFunc("/v2/functions/{function}", api.FunctionApiUpdate).Methods("PUT")
|
||||||
r.HandleFunc("/v2/functions/{function}", api.FunctionApiDelete).Methods("DELETE")
|
r.HandleFunc("/v2/functions/{function}", api.FunctionApiDelete).Methods("DELETE")
|
||||||
|
r.HandleFunc("/v2/functions/{function}/pods", api.FunctionApiPodList).Methods("GET")
|
||||||
|
|
||||||
r.HandleFunc("/v2/triggers/http", api.HTTPTriggerApiList).Methods("GET")
|
r.HandleFunc("/v2/triggers/http", api.HTTPTriggerApiList).Methods("GET")
|
||||||
r.HandleFunc("/v2/triggers/http", api.HTTPTriggerApiCreate).Methods("POST")
|
r.HandleFunc("/v2/triggers/http", api.HTTPTriggerApiCreate).Methods("POST")
|
||||||
@@ -226,6 +227,7 @@ func (api *API) GetHandler() http.Handler {
|
|||||||
r.HandleFunc("/v2/environments/{environment}", api.EnvironmentApiGet).Methods("GET")
|
r.HandleFunc("/v2/environments/{environment}", api.EnvironmentApiGet).Methods("GET")
|
||||||
r.HandleFunc("/v2/environments/{environment}", api.EnvironmentApiUpdate).Methods("PUT")
|
r.HandleFunc("/v2/environments/{environment}", api.EnvironmentApiUpdate).Methods("PUT")
|
||||||
r.HandleFunc("/v2/environments/{environment}", api.EnvironmentApiDelete).Methods("DELETE")
|
r.HandleFunc("/v2/environments/{environment}", api.EnvironmentApiDelete).Methods("DELETE")
|
||||||
|
r.HandleFunc("/v2/environments/{environment}/pods", api.EnvironmentApiPodList).Methods("GET")
|
||||||
|
|
||||||
r.HandleFunc("/v2/watches", api.WatchApiList).Methods("GET")
|
r.HandleFunc("/v2/watches", api.WatchApiList).Methods("GET")
|
||||||
r.HandleFunc("/v2/watches", api.WatchApiCreate).Methods("POST")
|
r.HandleFunc("/v2/watches", api.WatchApiCreate).Methods("POST")
|
||||||
|
|||||||
@@ -19,12 +19,13 @@ package v1
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
"github.com/fission/fission/pkg/controller/client/rest"
|
apiv1 "k8s.io/api/core/v1"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||||
|
"github.com/fission/fission/pkg/controller/client/rest"
|
||||||
"github.com/fission/fission/pkg/generator/encoder"
|
"github.com/fission/fission/pkg/generator/encoder"
|
||||||
v1generator "github.com/fission/fission/pkg/generator/v1"
|
v1generator "github.com/fission/fission/pkg/generator/v1"
|
||||||
)
|
)
|
||||||
@@ -40,6 +41,7 @@ type (
|
|||||||
Update(env *fv1.Environment) (*metav1.ObjectMeta, error)
|
Update(env *fv1.Environment) (*metav1.ObjectMeta, error)
|
||||||
Delete(m *metav1.ObjectMeta) error
|
Delete(m *metav1.ObjectMeta) error
|
||||||
List(ns string) ([]fv1.Environment, error)
|
List(ns string) ([]fv1.Environment, error)
|
||||||
|
ListPods(m *metav1.ObjectMeta) ([]apiv1.Pod, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
Environment struct {
|
Environment struct {
|
||||||
@@ -163,3 +165,38 @@ func (c *Environment) List(ns string) ([]fv1.Environment, error) {
|
|||||||
|
|
||||||
return envs, nil
|
return envs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Environment) ListPods(m *metav1.ObjectMeta) ([]apiv1.Pod, error) {
|
||||||
|
relativeUrl := fmt.Sprintf("environments/%s/pods", m.Name)
|
||||||
|
|
||||||
|
values := url.Values{}
|
||||||
|
if len(m.Labels) != 0 {
|
||||||
|
if envns, ok := m.Labels[fv1.ENVIRONMENT_NAMESPACE]; ok && len(envns) != 0 {
|
||||||
|
values.Add(fv1.ENVIRONMENT_NAMESPACE, envns)
|
||||||
|
|
||||||
|
}
|
||||||
|
if extype, ok := m.Labels[fv1.EXECUTOR_TYPE]; ok && len(extype) != 0 {
|
||||||
|
values.Add(fv1.EXECUTOR_TYPE, extype)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
relativeUrl = fmt.Sprintf("%s?%s", relativeUrl, values.Encode())
|
||||||
|
resp, err := c.client.Get(relativeUrl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := handleResponse(resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pods := make([]apiv1.Pod, 0)
|
||||||
|
err = json.Unmarshal(body, &pods)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pods, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package fake
|
package fake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
apiv1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||||
@@ -50,3 +51,7 @@ func (c *FakeEnvironment) Delete(m *metav1.ObjectMeta) error {
|
|||||||
func (c *FakeEnvironment) List(ns string) ([]fv1.Environment, error) {
|
func (c *FakeEnvironment) List(ns string) ([]fv1.Environment, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FakeEnvironment) ListPods(m *metav1.ObjectMeta) ([]apiv1.Pod, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package fake
|
package fake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
apiv1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||||
@@ -54,3 +55,7 @@ func (c *FakeFunction) Delete(m *metav1.ObjectMeta) error {
|
|||||||
func (c *FakeFunction) List(functionNamespace string) ([]fv1.Function, error) {
|
func (c *FakeFunction) List(functionNamespace string) ([]fv1.Function, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FakeFunction) ListPods(m *metav1.ObjectMeta) ([]apiv1.Pod, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ package v1
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
apiv1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||||
@@ -38,6 +40,7 @@ type (
|
|||||||
Update(f *fv1.Function) (*metav1.ObjectMeta, error)
|
Update(f *fv1.Function) (*metav1.ObjectMeta, error)
|
||||||
Delete(m *metav1.ObjectMeta) error
|
Delete(m *metav1.ObjectMeta) error
|
||||||
List(functionNamespace string) ([]fv1.Function, error)
|
List(functionNamespace string) ([]fv1.Function, error)
|
||||||
|
ListPods(m *metav1.ObjectMeta) ([]apiv1.Pod, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
Function struct {
|
Function struct {
|
||||||
@@ -176,3 +179,34 @@ func (c *Function) List(functionNamespace string) ([]fv1.Function, error) {
|
|||||||
|
|
||||||
return funcs, nil
|
return funcs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Function) ListPods(m *metav1.ObjectMeta) ([]apiv1.Pod, error) {
|
||||||
|
relativeUrl := fmt.Sprintf("functions/%s/pods", m.Name)
|
||||||
|
|
||||||
|
values := url.Values{}
|
||||||
|
if len(m.Labels) != 0 {
|
||||||
|
if fns, ok := m.Labels[fv1.FUNCTION_NAMESPACE]; ok && len(fns) != 0 {
|
||||||
|
values.Add(fv1.FUNCTION_NAMESPACE, fns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
relativeUrl = fmt.Sprintf("%s?%s", relativeUrl, values.Encode())
|
||||||
|
resp, err := c.client.Get(relativeUrl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := handleResponse(resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pods := make([]apiv1.Pod, 0)
|
||||||
|
err = json.Unmarshal(body, &pods)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pods, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,8 +27,10 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
|
||||||
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||||
|
v1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||||
ferror "github.com/fission/fission/pkg/error"
|
ferror "github.com/fission/fission/pkg/error"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -237,3 +239,44 @@ func (a *API) EnvironmentApiDelete(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
a.respondWithSuccess(w, []byte(""))
|
a.respondWithSuccess(w, []byte(""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnvironmentApiPodList: Get list of pods currently available in environment
|
||||||
|
func (a *API) EnvironmentApiPodList(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
envName, ok := vars["environment"]
|
||||||
|
if !ok {
|
||||||
|
a.respondWithError(w, ferror.MakeError(http.StatusInternalServerError, "Error retrieving environment name"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// label selector
|
||||||
|
selector := map[string]string{
|
||||||
|
fv1.ENVIRONMENT_NAME: envName,
|
||||||
|
}
|
||||||
|
|
||||||
|
ens := a.extractQueryParamFromRequest(r, v1.ENVIRONMENT_NAMESPACE)
|
||||||
|
if len(ens) != 0 {
|
||||||
|
selector[fv1.ENVIRONMENT_NAMESPACE] = ens
|
||||||
|
}
|
||||||
|
|
||||||
|
et := a.extractQueryParamFromRequest(r, v1.EXECUTOR_TYPE)
|
||||||
|
if len(et) != 0 {
|
||||||
|
selector[fv1.EXECUTOR_TYPE] = et
|
||||||
|
}
|
||||||
|
|
||||||
|
pods, err := a.kubernetesClient.CoreV1().Pods(metav1.NamespaceAll).List(r.Context(), metav1.ListOptions{
|
||||||
|
LabelSelector: labels.Set(selector).AsSelector().String(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
a.respondWithError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := json.Marshal(pods.Items)
|
||||||
|
if err != nil {
|
||||||
|
a.respondWithError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
a.respondWithSuccess(w, resp)
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import (
|
|||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||||
|
v1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||||
ferror "github.com/fission/fission/pkg/error"
|
ferror "github.com/fission/fission/pkg/error"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -369,3 +370,39 @@ func getContainerLog(kubernetesClient *kubernetes.Clientset, w http.ResponseWrit
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FunctionApiPodList: Get list of pods currently used by function
|
||||||
|
func (a *API) FunctionApiPodList(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
fnName, ok := vars["function"]
|
||||||
|
if !ok {
|
||||||
|
a.respondWithError(w, ferror.MakeError(http.StatusInternalServerError, "Error retrieving function name"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// label selector
|
||||||
|
selector := map[string]string{
|
||||||
|
fv1.FUNCTION_NAME: fnName,
|
||||||
|
}
|
||||||
|
|
||||||
|
fns := a.extractQueryParamFromRequest(r, v1.FUNCTION_NAMESPACE)
|
||||||
|
if len(fns) != 0 {
|
||||||
|
selector[fv1.FUNCTION_NAMESPACE] = fns
|
||||||
|
}
|
||||||
|
|
||||||
|
pods, err := a.kubernetesClient.CoreV1().Pods(metav1.NamespaceAll).List(r.Context(), metav1.ListOptions{
|
||||||
|
LabelSelector: labels.Set(selector).AsSelector().String(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
a.respondWithError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := json.Marshal(pods.Items)
|
||||||
|
if err != nil {
|
||||||
|
a.respondWithError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
a.respondWithSuccess(w, resp)
|
||||||
|
}
|
||||||
|
|||||||
@@ -85,13 +85,25 @@ func Commands() *cobra.Command {
|
|||||||
Optional: []flag.Flag{flag.NamespaceEnvironment},
|
Optional: []flag.Flag{flag.NamespaceEnvironment},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
listPodsCmd := &cobra.Command{
|
||||||
|
Use: "pods",
|
||||||
|
Aliases: []string{"pod", "po"},
|
||||||
|
Short: "List pods currently maintained by an environment",
|
||||||
|
Long: "List pods currently maintained by an environment",
|
||||||
|
RunE: wrapper.Wrapper(ListPods),
|
||||||
|
}
|
||||||
|
wrapper.SetFlags(listPodsCmd, flag.FlagSet{
|
||||||
|
Required: []flag.Flag{flag.EnvName},
|
||||||
|
Optional: []flag.Flag{flag.NamespaceEnvironment, flag.EnvExecutorType},
|
||||||
|
})
|
||||||
|
|
||||||
command := &cobra.Command{
|
command := &cobra.Command{
|
||||||
Use: "environment",
|
Use: "environment",
|
||||||
Aliases: []string{"env"},
|
Aliases: []string{"env"},
|
||||||
Short: "Create, update and manage environments",
|
Short: "Create, update and manage environments",
|
||||||
}
|
}
|
||||||
|
|
||||||
command.AddCommand(createCmd, getCmd, updateCmd, deleteCmd, listCmd)
|
command.AddCommand(createCmd, getCmd, updateCmd, deleteCmd, listCmd, listPodsCmd)
|
||||||
|
|
||||||
return command
|
return command
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 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 environment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"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/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListPodsSubCommand struct {
|
||||||
|
cmd.CommandActioner
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListPods(input cli.Input) error {
|
||||||
|
return (&ListPodsSubCommand{}).do(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opts *ListPodsSubCommand) do(input cli.Input) error {
|
||||||
|
|
||||||
|
m := &metav1.ObjectMeta{
|
||||||
|
Name: input.String(flagkey.EnvName),
|
||||||
|
Labels: map[string]string{
|
||||||
|
v1.ENVIRONMENT_NAMESPACE: input.String(flagkey.NamespaceEnvironment),
|
||||||
|
v1.EXECUTOR_TYPE: input.String(flagkey.EnvExecutorType),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pods, err := opts.Client().V1().Environment().ListPods(m)
|
||||||
|
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 {
|
||||||
|
|
||||||
|
// A deletion timestamp indicates that a pod is terminating. Do not count this pod.
|
||||||
|
if pod.ObjectMeta.DeletionTimestamp != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
labelList := pod.GetLabels()
|
||||||
|
readyContainers, noOfContainers := utils.PodContainerReadyStatus(&pod)
|
||||||
|
fmt.Fprintf(w, "%v\t%v\t%v/%v\t%v\t%v\t%v\t%v\t\n", pod.ObjectMeta.Name, pod.ObjectMeta.Namespace, noOfContainers, readyContainers, pod.Status.Phase, pod.Status.PodIP, labelList[v1.EXECUTOR_TYPE], labelList[v1.MANAGED])
|
||||||
|
}
|
||||||
|
w.Flush()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -201,13 +201,25 @@ func Commands() *cobra.Command {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
listPodsCmd := &cobra.Command{
|
||||||
|
Use: "pods",
|
||||||
|
Aliases: []string{"pod", "po"},
|
||||||
|
Short: "List pods currently used by a function",
|
||||||
|
Long: "List pods currently used by a function",
|
||||||
|
RunE: wrapper.Wrapper(ListPods),
|
||||||
|
}
|
||||||
|
wrapper.SetFlags(listPodsCmd, flag.FlagSet{
|
||||||
|
Required: []flag.Flag{flag.FnName},
|
||||||
|
Optional: []flag.Flag{flag.NamespaceFunction},
|
||||||
|
})
|
||||||
|
|
||||||
command := &cobra.Command{
|
command := &cobra.Command{
|
||||||
Use: "function",
|
Use: "function",
|
||||||
Aliases: []string{"fn"},
|
Aliases: []string{"fn"},
|
||||||
Short: "Create, update and manage functions",
|
Short: "Create, update and manage functions",
|
||||||
}
|
}
|
||||||
command.AddCommand(createCmd, getCmd, getmetaCmd, updateCmd, deleteCmd, listCmd, logsCmd, testCmd,
|
command.AddCommand(createCmd, getCmd, getmetaCmd, updateCmd, deleteCmd, listCmd, logsCmd, testCmd,
|
||||||
runContainerCmd, updateContainerCmd)
|
runContainerCmd, updateContainerCmd, listPodsCmd)
|
||||||
|
|
||||||
return command
|
return command
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 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 function
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"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/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListPodsSubCommand struct {
|
||||||
|
cmd.CommandActioner
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListPods(input cli.Input) error {
|
||||||
|
return (&ListPodsSubCommand{}).do(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opts *ListPodsSubCommand) do(input cli.Input) error {
|
||||||
|
|
||||||
|
m := &metav1.ObjectMeta{
|
||||||
|
Name: input.String(flagkey.FnName),
|
||||||
|
Labels: map[string]string{
|
||||||
|
v1.FUNCTION_NAMESPACE: input.String(flagkey.NamespaceFunction),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pods, err := opts.Client().V1().Function().ListPods(m)
|
||||||
|
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 {
|
||||||
|
|
||||||
|
// A deletion timestamp indicates that a pod is terminating. Do not count this pod.
|
||||||
|
if pod.ObjectMeta.DeletionTimestamp != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
labelList := pod.GetLabels()
|
||||||
|
readyContainers, noOfContainers := utils.PodContainerReadyStatus(&pod)
|
||||||
|
fmt.Fprintf(w, "%v\t%v\t%v/%v\t%v\t%v\t%v\t%v\t\n", pod.ObjectMeta.Name, pod.ObjectMeta.Namespace, noOfContainers, readyContainers, pod.Status.Phase, pod.Status.PodIP, labelList[v1.EXECUTOR_TYPE], labelList[v1.MANAGED])
|
||||||
|
}
|
||||||
|
w.Flush()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -167,6 +167,7 @@ var (
|
|||||||
EnvTerminationGracePeriod = Flag{Type: Int64, Name: flagkey.EnvGracePeriod, Aliases: []string{"period"}, Usage: "Grace time (in seconds) for pod to perform connection draining before termination (default value will be used if 0 is given)", DefaultValue: 360}
|
EnvTerminationGracePeriod = Flag{Type: Int64, Name: flagkey.EnvGracePeriod, Aliases: []string{"period"}, Usage: "Grace time (in seconds) for pod to perform connection draining before termination (default value will be used if 0 is given)", DefaultValue: 360}
|
||||||
EnvVersion = Flag{Type: Int, Name: flagkey.EnvVersion, Usage: "Environment API version (1 means v1 interface)", DefaultValue: 1}
|
EnvVersion = Flag{Type: Int, Name: flagkey.EnvVersion, Usage: "Environment API version (1 means v1 interface)", DefaultValue: 1}
|
||||||
EnvImagePullSecret = Flag{Type: String, Name: flagkey.EnvImagePullSecret, Usage: "Secret for Kubernetes to pull an image from a private registry"}
|
EnvImagePullSecret = Flag{Type: String, Name: flagkey.EnvImagePullSecret, Usage: "Secret for Kubernetes to pull an image from a private registry"}
|
||||||
|
EnvExecutorType = Flag{Type: String, Name: flagkey.EnvExecutorType, Usage: "Executor type of pod in environment; one of 'poolmgr', 'newdeploy', 'container'"}
|
||||||
|
|
||||||
KwName = Flag{Type: String, Name: flagkey.KwName, Usage: "Watch name"}
|
KwName = Flag{Type: String, Name: flagkey.KwName, Usage: "Watch name"}
|
||||||
KwFnName = Flag{Type: String, Name: flagkey.KwFnName, Usage: "Function name"}
|
KwFnName = Flag{Type: String, Name: flagkey.KwFnName, Usage: "Function name"}
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ const (
|
|||||||
EnvGracePeriod = "graceperiod"
|
EnvGracePeriod = "graceperiod"
|
||||||
EnvVersion = "version"
|
EnvVersion = "version"
|
||||||
EnvImagePullSecret = "imagepullsecret"
|
EnvImagePullSecret = "imagepullsecret"
|
||||||
|
EnvExecutorType = "executortype"
|
||||||
|
|
||||||
KwName = resourceName
|
KwName = resourceName
|
||||||
KwFnName = "function"
|
KwFnName = "function"
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 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 utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsReadyPod checks both all containers in a pod are ready and whether
|
||||||
|
// the .metadata.DeletionTimestamp is nil.
|
||||||
|
func IsReadyPod(pod *v1.Pod) bool {
|
||||||
|
// since its a utility function, just ensuring there is no nil pointer exception
|
||||||
|
if pod == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// pod is in "Terminating" status if deletionTimestamp is not nil
|
||||||
|
// https://github.com/kubernetes/kubernetes/issues/61376
|
||||||
|
if pod.ObjectMeta.DeletionTimestamp != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// pod does not have an IP address allocated to it yet
|
||||||
|
if pod.Status.PodIP == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cStatus := range pod.Status.ContainerStatuses {
|
||||||
|
if !cStatus.Ready {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodContainerReadyStatus returns the number of ready containers and total containers present in pod
|
||||||
|
func PodContainerReadyStatus(pod *v1.Pod) (readyContainers, noOfContainers int) {
|
||||||
|
|
||||||
|
noOfContainers = len(pod.Status.ContainerStatuses)
|
||||||
|
readyContainers = 0
|
||||||
|
|
||||||
|
for _, status := range pod.Status.ContainerStatuses {
|
||||||
|
if status.Ready {
|
||||||
|
readyContainers++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -58,34 +58,6 @@ func GetFunctionIstioServiceName(fnName, fnNamespace string) string {
|
|||||||
return fmt.Sprintf("istio-%v-%v", fnName, fnNamespace)
|
return fmt.Sprintf("istio-%v-%v", fnName, fnNamespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsReadyPod checks both all containers in a pod are ready and whether
|
|
||||||
// the .metadata.DeletionTimestamp is nil.
|
|
||||||
func IsReadyPod(pod *apiv1.Pod) bool {
|
|
||||||
// since its a utility function, just ensuring there is no nil pointer exception
|
|
||||||
if pod == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// pod is in "Terminating" status if deletionTimestamp is not nil
|
|
||||||
// https://github.com/kubernetes/kubernetes/issues/61376
|
|
||||||
if pod.ObjectMeta.DeletionTimestamp != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// pod does not have an IP address allocated to it yet
|
|
||||||
if pod.Status.PodIP == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, cStatus := range pod.Status.ContainerStatuses {
|
|
||||||
if !cStatus.Ready {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTempDir creates and return a temporary directory
|
// GetTempDir creates and return a temporary directory
|
||||||
func GetTempDir() (string, error) {
|
func GetTempDir() (string, error) {
|
||||||
id, err := uuid.NewV4()
|
id, err := uuid.NewV4()
|
||||||
|
|||||||
Reference in New Issue
Block a user