Enabling multi-tenancy for fission objects. (#655)

This feature allows creation of fission objects in different namespaces, in addition to retaining the existing behavior of creating fission objects in default namespace if user doesnt provide one. 
It also removes cluster admin roles for fission-fetcher and fission-builder Service Accounts and grants them only those privileges that they need.
This commit is contained in:
smruthi2187
2018-05-23 13:22:46 -07:00
committed by GitHub
parent c9d2757760
commit 8984e4916e
62 changed files with 1962 additions and 495 deletions
+1 -1
View File
@@ -66,7 +66,7 @@ func (w *packageBuildWatcher) watch(ctx context.Context) {
}
// poll list of packages (TODO: convert to watch)
pkgs, err := w.fclient.PackageList()
pkgs, err := w.fclient.PackageList(metav1.NamespaceAll)
checkErr(err, "Getting list of packages")
// find packages that (a) are in the app spec and (b) have an interesting
+3 -3
View File
@@ -205,10 +205,10 @@ func createArchive(client *client.Client, fileName string, specFile string) *fis
return &archive
}
func createPackage(client *client.Client, envName, srcArchiveName, deployArchiveName, buildcmd string, specFile string) *metav1.ObjectMeta {
func createPackage(client *client.Client, pkgNamespace, envName, envNamespace, srcArchiveName, deployArchiveName, buildcmd string, specFile string) *metav1.ObjectMeta {
pkgSpec := fission.PackageSpec{
Environment: fission.EnvironmentReference{
Namespace: metav1.NamespaceDefault,
Namespace: envNamespace,
Name: envName,
},
}
@@ -239,7 +239,7 @@ func createPackage(client *client.Client, envName, srcArchiveName, deployArchive
pkg := &crd.Package{
Metadata: metav1.ObjectMeta{
Name: pkgName,
Namespace: metav1.NamespaceDefault,
Namespace: pkgNamespace,
},
Spec: pkgSpec,
Status: fission.PackageStatus{
+33 -6
View File
@@ -28,9 +28,24 @@ import (
"k8s.io/client-go/pkg/api/v1"
"github.com/fission/fission"
"github.com/fission/fission/controller/client"
"github.com/fission/fission/crd"
)
func getFunctionsByEnvironment(client *client.Client, envName, envNamespace string) ([]crd.Function, error) {
fnList, err := client.FunctionList(metav1.NamespaceAll)
if err != nil {
return nil, err
}
fns := []crd.Function{}
for _, fn := range fnList {
if fn.Spec.Environment.Name == envName && fn.Spec.Environment.Namespace == envNamespace {
fns = append(fns, fn)
}
}
return fns, nil
}
func envCreate(c *cli.Context) error {
client := getClient(c.GlobalString("server"))
@@ -38,6 +53,14 @@ func envCreate(c *cli.Context) error {
if len(envName) == 0 {
fatal("Need a name, use --name.")
}
envNamespace := c.String("envNamespace")
envList, err := client.EnvironmentList(envNamespace)
if err == nil && len(envList) > 0 {
warn(fmt.Sprintf("%d environment(s) are present in this ns: %s. All these envs share"+
" the same service account token, with previleges to view secrets of all the functions referencing them. "+
"Envs can be created in different ns if isolation is needed", len(envList), envNamespace))
}
var poolsize int
if c.IsSet("poolsize") {
@@ -80,7 +103,7 @@ func envCreate(c *cli.Context) error {
env := &crd.Environment{
Metadata: metav1.ObjectMeta{
Name: envName,
Namespace: metav1.NamespaceDefault,
Namespace: envNamespace,
},
Spec: fission.EnvironmentSpec{
Version: envVersion,
@@ -106,7 +129,7 @@ func envCreate(c *cli.Context) error {
return nil
}
_, err := client.EnvironmentCreate(env)
_, err = client.EnvironmentCreate(env)
checkErr(err, "create environment")
fmt.Printf("environment '%v' created\n", envName)
@@ -120,10 +143,11 @@ func envGet(c *cli.Context) error {
if len(envName) == 0 {
fatal("Need a name, use --name.")
}
envNamespace := c.String("envNamespace")
m := &metav1.ObjectMeta{
Name: envName,
Namespace: metav1.NamespaceDefault,
Namespace: envNamespace,
}
env, err := client.EnvironmentGet(m)
checkErr(err, "get environment")
@@ -143,6 +167,7 @@ func envUpdate(c *cli.Context) error {
if len(envName) == 0 {
fatal("Need a name, use --name.")
}
envNamespace := c.String("envNamespace")
envImg := c.String("image")
envBuilderImg := c.String("builder")
@@ -155,7 +180,7 @@ func envUpdate(c *cli.Context) error {
env, err := client.EnvironmentGet(&metav1.ObjectMeta{
Name: envName,
Namespace: metav1.NamespaceDefault,
Namespace: envNamespace,
})
checkErr(err, "find environment")
@@ -198,10 +223,11 @@ func envDelete(c *cli.Context) error {
if len(envName) == 0 {
fatal("Need a name , use --name.")
}
envNamespace := c.String("envNamespace")
m := &metav1.ObjectMeta{
Name: envName,
Namespace: metav1.NamespaceDefault,
Namespace: envNamespace,
}
err := client.EnvironmentDelete(m)
checkErr(err, "delete environment")
@@ -212,8 +238,9 @@ func envDelete(c *cli.Context) error {
func envList(c *cli.Context) error {
client := getClient(c.GlobalString("server"))
envNamespace := c.String("envNamespace")
envs, err := client.EnvironmentList()
envs, err := client.EnvironmentList(envNamespace)
checkErr(err, "list environments")
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
+82 -38
View File
@@ -30,6 +30,7 @@ import (
"github.com/satori/go.uuid"
"github.com/urfave/cli"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
apiv1 "k8s.io/client-go/pkg/api/v1"
@@ -115,9 +116,13 @@ func getTargetCPU(c *cli.Context) int {
return targetCPU
}
// From this change onwards, we mandate that a function should reference a secret, config map and package in its own ns
func fnCreate(c *cli.Context) error {
client := getClient(c.GlobalString("server"))
fnNamespace := c.String("fnNamespace")
envNamespace := c.String("envNamespace")
fnName := c.String("name")
if len(fnName) == 0 {
fatal("Need --name argument.")
@@ -131,7 +136,8 @@ func fnCreate(c *cli.Context) error {
specFile = fmt.Sprintf("function-%v.yaml", fnName)
}
fnList, err := client.FunctionList()
// check for unique function names within a namespace
fnList, err := client.FunctionList(fnNamespace)
checkErr(err, "get function list")
// check function existence before creating package
for _, fn := range fnList {
@@ -148,18 +154,16 @@ func fnCreate(c *cli.Context) error {
secretName := c.String("secret")
cfgMapName := c.String("configmap")
secretNameSpace := c.String("secretNamespace")
cfgMapNameSpace := c.String("configmapNamespace")
if len(pkgName) > 0 {
// use existing package
pkg, err := client.PackageGet(&metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
Name: pkgName,
})
checkErr(err, fmt.Sprintf("read package '%v'", pkgName))
checkErr(err, fmt.Sprintf("read package in '%v' in Namespace: %s. Package needs to be present in the same namespace as function", pkgName, fnNamespace))
pkgMetadata = &pkg.Metadata
envName = pkg.Spec.Environment.Name
envNamespace = pkg.Spec.Environment.Namespace
} else {
// need to specify environment for creating new package
envName = c.String("env")
@@ -169,7 +173,7 @@ func fnCreate(c *cli.Context) error {
// examine existence of given environment
_, err := client.EnvironmentGet(&metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Namespace: envNamespace,
Name: envName,
})
if err != nil {
@@ -192,8 +196,8 @@ func fnCreate(c *cli.Context) error {
buildcmd := c.String("buildcmd")
// create new package
pkgMetadata = createPackage(client, envName, srcArchiveName, deployArchiveName, buildcmd, specFile)
// create new package in the same namespace as the function.
pkgMetadata = createPackage(client, fnNamespace, envName, envNamespace, srcArchiveName, deployArchiveName, buildcmd, specFile)
}
invokeStrategy := getInvokeStrategy(c.Int("minscale"), c.Int("maxscale"), c.String("executortype"), getTargetCPU(c))
@@ -207,23 +211,35 @@ func fnCreate(c *cli.Context) error {
var cfgmaps []fission.ConfigMapReference
if len(secretName) > 0 {
if len(secretNameSpace) == 0 {
secretNameSpace = metav1.NamespaceDefault
// check the referenced secret is in the same ns as the function, if not give a warning.
_, err := client.SecretGet(&metav1.ObjectMeta{
Namespace: fnNamespace,
Name: secretName,
})
if k8serrors.IsNotFound(err) {
warn(fmt.Sprintf("Secret %s not found in Namespace: %s. Secret needs to be present in the same namespace as function", secretName, fnNamespace))
}
newSecret := fission.SecretReference{
Name: secretName,
Namespace: secretNameSpace,
Namespace: fnNamespace,
}
secrets = []fission.SecretReference{newSecret}
}
if len(cfgMapName) > 0 {
if len(cfgMapNameSpace) == 0 {
cfgMapNameSpace = metav1.NamespaceDefault
// check the referenced cfgmap is in the same ns as the function, if not give a warning.
_, err := client.ConfigMapGet(&metav1.ObjectMeta{
Namespace: fnNamespace,
Name: cfgMapName,
})
if k8serrors.IsNotFound(err) {
warn(fmt.Sprintf("ConfigMap %s not found in Namespace: %s. ConfigMap needs to be present in the same namespace as function", cfgMapName, fnNamespace))
}
newCfgMap := fission.ConfigMapReference{
Name: cfgMapName,
Namespace: cfgMapNameSpace,
Namespace: fnNamespace,
}
cfgmaps = []fission.ConfigMapReference{newCfgMap}
}
@@ -231,12 +247,12 @@ func fnCreate(c *cli.Context) error {
function := &crd.Function{
Metadata: metav1.ObjectMeta{
Name: fnName,
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
},
Spec: fission.FunctionSpec{
Environment: fission.EnvironmentReference{
Name: envName,
Namespace: metav1.NamespaceDefault,
Namespace: envNamespace,
},
Package: fission.FunctionPackageRef{
FunctionName: entrypoint,
@@ -283,7 +299,7 @@ func fnCreate(c *cli.Context) error {
ht := &crd.HTTPTrigger{
Metadata: metav1.ObjectMeta{
Name: triggerName,
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
},
Spec: fission.HTTPTriggerSpec{
RelativeURL: triggerUrl,
@@ -308,9 +324,10 @@ func fnGet(c *cli.Context) error {
if len(fnName) == 0 {
fatal("Need name of function, use --name")
}
fnNamespace := c.String("fnNamespace")
m := &metav1.ObjectMeta{
Name: fnName,
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
}
fn, err := client.FunctionGet(m)
checkErr(err, "get function")
@@ -332,10 +349,11 @@ func fnGetMeta(c *cli.Context) error {
if len(fnName) == 0 {
fatal("Need name of function, use --name")
}
fnNamespace := c.String("fnNamespace")
m := &metav1.ObjectMeta{
Name: fnName,
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
}
f, err := client.FunctionGet(m)
@@ -364,14 +382,16 @@ func fnUpdate(c *cli.Context) error {
if len(fnName) == 0 {
fatal("Need name of function, use --name")
}
fnNamespace := c.String("fnNamespace")
function, err := client.FunctionGet(&metav1.ObjectMeta{
Name: fnName,
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
})
checkErr(err, fmt.Sprintf("read function '%v'", fnName))
envName := c.String("env")
envNamespace := c.String("envNamespace")
deployArchiveName := c.String("code")
if len(deployArchiveName) == 0 {
deployArchiveName = c.String("deploy")
@@ -385,9 +405,6 @@ func fnUpdate(c *cli.Context) error {
secretName := c.String("secret")
cfgMapName := c.String("configmap")
secretNameSpace := c.String("secretNamespace")
cfgMapNameSpace := c.String("configmapNamespace")
if len(srcArchiveName) > 0 && len(deployArchiveName) > 0 {
fatal("Need either of --src or --deploy and not both arguments.")
}
@@ -396,12 +413,19 @@ func fnUpdate(c *cli.Context) error {
if len(function.Spec.Secrets) > 1 {
fatal("Please use 'fission spec apply' to update list of secrets")
}
if len(secretNameSpace) == 0 {
secretNameSpace = metav1.NamespaceDefault
// check that the referenced secret is in the same ns as the function, if not give a warning.
_, err := client.SecretGet(&metav1.ObjectMeta{
Namespace: fnNamespace,
Name: secretName,
})
if k8serrors.IsNotFound(err) {
warn(fmt.Sprintf("secret %s not found in Namespace: %s. Secret needs to be present in the same namespace as function", secretName, fnNamespace))
}
newSecret := fission.SecretReference{
Name: secretName,
Namespace: secretNameSpace,
Namespace: fnNamespace,
}
function.Spec.Secrets = []fission.SecretReference{newSecret}
}
@@ -410,18 +434,26 @@ func fnUpdate(c *cli.Context) error {
if len(function.Spec.ConfigMaps) > 1 {
fatal("Please use 'fission spec apply' to update list of configmaps")
}
if len(cfgMapNameSpace) == 0 {
cfgMapNameSpace = metav1.NamespaceDefault
// check that the referenced cfgmap is in the same ns as the function, if not give a warning.
_, err := client.ConfigMapGet(&metav1.ObjectMeta{
Namespace: fnNamespace,
Name: cfgMapName,
})
if k8serrors.IsNotFound(err) {
warn(fmt.Sprintf("ConfigMap %s not found in Namespace: %s. ConfigMap needs to be present in the same namespace as the function", cfgMapName, fnNamespace))
}
newCfgMap := fission.ConfigMapReference{
Name: cfgMapName,
Namespace: cfgMapNameSpace,
Namespace: fnNamespace,
}
function.Spec.ConfigMaps = []fission.ConfigMapReference{newCfgMap}
}
if len(envName) > 0 {
function.Spec.Environment.Name = envName
function.Spec.Environment.Namespace = envNamespace
}
if len(entrypoint) > 0 {
@@ -432,22 +464,22 @@ func fnUpdate(c *cli.Context) error {
}
pkg, err := client.PackageGet(&metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
Name: pkgName,
})
checkErr(err, fmt.Sprintf("read package '%v'", pkgName))
checkErr(err, fmt.Sprintf("read package '%v.%v'. Pkg should be present in the same ns as the function", pkgName, fnNamespace))
pkgMetadata := &pkg.Metadata
if len(deployArchiveName) != 0 || len(srcArchiveName) != 0 || len(buildcmd) != 0 || len(envName) != 0 {
fnList, err := getFunctionsByPackage(client, pkg.Metadata.Name)
fnList, err := getFunctionsByPackage(client, pkg.Metadata.Name, pkg.Metadata.Namespace)
checkErr(err, "get function list")
if !force && len(fnList) > 1 {
fatal("Package is used by multiple functions, use --force to force update")
}
pkgMetadata = updatePackage(client, pkg, envName, srcArchiveName, deployArchiveName, buildcmd)
pkgMetadata = updatePackage(client, pkg, envName, envNamespace, srcArchiveName, deployArchiveName, buildcmd)
checkErr(err, fmt.Sprintf("update package '%v'", pkgName))
fmt.Printf("package '%v' updated\n", pkgMetadata.GetName())
@@ -463,6 +495,9 @@ func fnUpdate(c *cli.Context) error {
}
}
// TODO : One corner case where user just updates the pkg reference with fnUpdate, but internally this new pkg reference
// references a diff env than the spec
// update function spec with new package metadata
function.Spec.Package.PackageRef = fission.PackageRef{
Namespace: pkgMetadata.Namespace,
@@ -532,10 +567,11 @@ func fnDelete(c *cli.Context) error {
if len(fnName) == 0 {
fatal("Need name of function, use --name")
}
fnNamespace := c.String("fnNamespace")
m := &metav1.ObjectMeta{
Name: fnName,
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
}
err := client.FunctionDelete(m)
@@ -547,8 +583,9 @@ func fnDelete(c *cli.Context) error {
func fnList(c *cli.Context) error {
client := getClient(c.GlobalString("server"))
ns := c.String("fnNamespace")
fns, err := client.FunctionList()
fns, err := client.FunctionList(ns)
checkErr(err, "list functions")
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
@@ -581,6 +618,7 @@ func fnLogs(c *cli.Context) error {
if len(fnName) == 0 {
fatal("Need name of function, use --name")
}
fnNamespace := c.String("fnNamespace")
dbType := c.String("dbtype")
if len(dbType) == 0 {
@@ -590,7 +628,7 @@ func fnLogs(c *cli.Context) error {
fnPod := c.String("pod")
m := &metav1.ObjectMeta{
Name: fnName,
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
}
recordLimit := c.Int("recordcount")
@@ -659,6 +697,7 @@ func fnTest(c *cli.Context) error {
if len(fnName) == 0 {
fatal("Need function name to be specified with --name")
}
ns := c.String("fnNamespace")
routerURL := os.Getenv("FISSION_ROUTER")
if len(routerURL) == 0 {
@@ -670,7 +709,12 @@ func fnTest(c *cli.Context) error {
routerURL = strings.TrimPrefix(routerURL, "http://")
}
url := fmt.Sprintf("http://%s/fission-function/%s", routerURL, fnName)
fnUri := fnName
if ns != metav1.NamespaceDefault {
fnUri = fmt.Sprintf("%v/%v", ns, fnName)
}
url := fmt.Sprintf("http://%s/fission-function/%s", routerURL, fnUri)
resp := httpRequest(c.String("method"), url, c.String("body"), c.StringSlice("header"))
if resp.StatusCode < 400 {
+13 -8
View File
@@ -58,10 +58,10 @@ func getMethod(method string) string {
return ""
}
func checkFunctionExistence(fissionClient *client.Client, fnName string) {
func checkFunctionExistence(fissionClient *client.Client, fnName string, fnNamespace string) {
meta := &metav1.ObjectMeta{
Name: fnName,
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
}
_, err := fissionClient.FunctionGet(meta)
@@ -77,6 +77,8 @@ func htCreate(c *cli.Context) error {
if len(fnName) == 0 {
fatal("Need a function name to create a trigger, use --function")
}
fnNamespace := c.String("fnNamespace")
triggerUrl := c.String("url")
if len(triggerUrl) == 0 {
fatal("Need a trigger URL, use --url")
@@ -90,7 +92,7 @@ func htCreate(c *cli.Context) error {
method = "GET"
}
checkFunctionExistence(client, fnName)
checkFunctionExistence(client, fnName, fnNamespace)
// just name triggers by uuid.
triggerName := uuid.NewV4().String()
@@ -98,7 +100,7 @@ func htCreate(c *cli.Context) error {
ht := &crd.HTTPTrigger{
Metadata: metav1.ObjectMeta{
Name: triggerName,
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
},
Spec: fission.HTTPTriggerSpec{
RelativeURL: triggerUrl,
@@ -135,6 +137,7 @@ func htUpdate(c *cli.Context) error {
if len(htName) == 0 {
fatal("Need name of trigger, use --name")
}
triggerNamespace := c.String("triggerNamespace")
// update function ref
newFn := c.String("function")
@@ -142,11 +145,11 @@ func htUpdate(c *cli.Context) error {
fatal("Nothing to update. Use --function to specify a new function.")
}
checkFunctionExistence(client, newFn)
checkFunctionExistence(client, newFn, triggerNamespace)
ht, err := client.HTTPTriggerGet(&metav1.ObjectMeta{
Name: htName,
Namespace: metav1.NamespaceDefault,
Namespace: triggerNamespace,
})
checkErr(err, "get HTTP trigger")
@@ -167,10 +170,11 @@ func htDelete(c *cli.Context) error {
if len(htName) == 0 {
fatal("Need name of trigger to delete, use --name")
}
triggerNamespace := c.String("triggerNamespace")
err := client.HTTPTriggerDelete(&metav1.ObjectMeta{
Name: htName,
Namespace: metav1.NamespaceDefault,
Namespace: triggerNamespace,
})
checkErr(err, "delete trigger")
@@ -180,8 +184,9 @@ func htDelete(c *cli.Context) error {
func htList(c *cli.Context) error {
client := getClient(c.GlobalString("server"))
triggerNamespace := c.String("triggerNamespace")
hts, err := client.HTTPTriggerList()
hts, err := client.HTTPTriggerList(triggerNamespace)
checkErr(err, "list HTTP triggers")
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
+51 -44
View File
@@ -26,6 +26,7 @@ import (
version "github.com/fission/fission"
"github.com/urfave/cli"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func getFissionNamespace() string {
@@ -107,6 +108,12 @@ func main() {
// all resource create commands accept --spec
specSaveFlag := cli.BoolFlag{Name: "spec", Usage: "Save to the spec directory instead of creating on cluster"}
// namespace reference for all objects
fnNamespaceFlag := cli.StringFlag{Name: "fnNamespace, fns", Value: metav1.NamespaceDefault, Usage: "Namespace for function object"}
envNamespaceFlag := cli.StringFlag{Name: "envNamespace, envns", Value: metav1.NamespaceDefault, Usage: "Namespace for environment object"}
pkgNamespaceFlag := cli.StringFlag{Name: "pkgNamespace, pkgns", Value: metav1.NamespaceDefault, Usage: "Namespace for package object"}
triggerNamespaceFlag := cli.StringFlag{Name: "triggerNamespace, triggerns", Value: metav1.NamespaceDefault, Usage: "Namespace for trigger object"}
// trigger method and url flags (used in function and route CLIs)
htMethodFlag := cli.StringFlag{Name: "method", Value: "GET", Usage: "HTTP Method: GET|POST|PUT|DELETE|HEAD"}
htUrlFlag := cli.StringFlag{Name: "url", Usage: "URL pattern (See gorilla/mux supported patterns)"}
@@ -126,7 +133,7 @@ func main() {
fnCodeFlag := cli.StringFlag{Name: "code", Usage: "local path or URL for source code"}
fnDeployArchiveFlag := cli.StringFlag{Name: "deployarchive, deploy", Usage: "local path or URL for deployment archive"}
fnSrcArchiveFlag := cli.StringFlag{Name: "sourcearchive, src", Usage: "local path or URL for source archive"}
fnPkgNameFlag := cli.StringFlag{Name: "pkgname, pkg", Usage: "Name of the existing package (--deploy and --src and --env will be ignored)"}
fnPkgNameFlag := cli.StringFlag{Name: "pkgname, pkg", Usage: "Name of the existing package (--deploy and --src and --env will be ignored), should be in the same namespace as the function"}
fnPodFlag := cli.StringFlag{Name: "pod", Usage: "function pod name, optional (use latest if unspecified)"}
fnFollowFlag := cli.BoolFlag{Name: "follow, f", Usage: "specify if the logs should be streamed"}
fnDetailFlag := cli.BoolFlag{Name: "detail, d", Usage: "display detailed information"}
@@ -135,34 +142,34 @@ func main() {
fnHeaderFlag := cli.StringSliceFlag{Name: "header, H", Usage: "request headers"}
fnEntryPointFlag := cli.StringFlag{Name: "entrypoint", Usage: "entry point for environment v2 to load with"}
fnBuildCmdFlag := cli.StringFlag{Name: "buildcmd", Usage: "build command for builder to run with"}
fnSecretFlag := cli.StringFlag{Name: "secret", Usage: "function access to secret"}
fnSecretnsFlag := cli.StringFlag{Name: "secretNamespace", Usage: "namespace of secret"}
fnCfgMapFlag := cli.StringFlag{Name: "configmap", Usage: "function access to configmap"}
fnCfgMapnsFlag := cli.StringFlag{Name: "configmapNamespace", Usage: "namespace of configmap"}
fnSecretFlag := cli.StringFlag{Name: "secret", Usage: "function access to secret, should be present in the same namespace as the function"}
fnCfgMapFlag := cli.StringFlag{Name: "configmap", Usage: "function access to configmap, should be present in the same namespace as the function"}
fnLogCountFlag := cli.StringFlag{Name: "recordcount", Usage: "the n most recent log records"}
fnForceFlag := cli.BoolFlag{Name: "force", Usage: "Force update a package even if it is used by one or more functions"}
fnExecutorTypeFlag := cli.StringFlag{Name: "executortype", Value: "poolmgr", Usage: "Executor type for execution; one of 'poolmgr', 'newdeploy'"}
fnExecutorTypeFlag := cli.StringFlag{Name: "executortype", Usage: "Executor type for execution; one of 'poolmgr', 'newdeploy' defaults to 'poolmgr'"}
fnSubcommands := []cli.Command{
{Name: "create", Usage: "Create new function (and optionally, an HTTP route to it)", Flags: []cli.Flag{fnNameFlag, fnEnvNameFlag, specSaveFlag, fnCodeFlag, fnSrcArchiveFlag, fnDeployArchiveFlag, fnEntryPointFlag, fnBuildCmdFlag, fnPkgNameFlag, htUrlFlag, htMethodFlag, minCpu, maxCpu, minMem, maxMem, minScale, maxScale, fnExecutorTypeFlag, targetcpu, fnCfgMapFlag, fnSecretFlag, fnSecretnsFlag, fnCfgMapnsFlag}, Action: fnCreate},
{Name: "get", Usage: "Get function source code", Flags: []cli.Flag{fnNameFlag}, Action: fnGet},
{Name: "getmeta", Usage: "Get function metadata", Flags: []cli.Flag{fnNameFlag}, Action: fnGetMeta},
{Name: "update", Usage: "Update function source code", Flags: []cli.Flag{fnNameFlag, fnEnvNameFlag, fnCodeFlag, fnSrcArchiveFlag, fnDeployArchiveFlag, fnEntryPointFlag, fnPkgNameFlag, fnBuildCmdFlag, fnForceFlag, minCpu, maxCpu, minMem, maxMem, minScale, maxScale, fnExecutorTypeFlag, targetcpu}, Action: fnUpdate},
{Name: "delete", Usage: "Delete function", Flags: []cli.Flag{fnNameFlag}, Action: fnDelete},
{Name: "list", Usage: "List all functions", Flags: []cli.Flag{}, Action: fnList},
{Name: "logs", Usage: "Display function logs", Flags: []cli.Flag{fnNameFlag, fnPodFlag, fnFollowFlag, fnDetailFlag, fnLogDBTypeFlag, fnLogCountFlag}, Action: fnLogs},
{Name: "test", Usage: "Test a function", Flags: []cli.Flag{fnNameFlag, fnEnvNameFlag, fnCodeFlag, fnSrcArchiveFlag, htMethodFlag, fnBodyFlag, fnHeaderFlag}, Action: fnTest},
{Name: "create", Usage: "Create new function (and optionally, an HTTP route to it)", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag, fnEnvNameFlag, envNamespaceFlag, specSaveFlag, fnCodeFlag, fnSrcArchiveFlag, fnDeployArchiveFlag, fnEntryPointFlag, fnBuildCmdFlag, fnPkgNameFlag, htUrlFlag, htMethodFlag, minCpu, maxCpu, minMem, maxMem, minScale, maxScale, fnExecutorTypeFlag, targetcpu, fnCfgMapFlag, fnSecretFlag}, Action: fnCreate},
{Name: "get", Usage: "Get function source code", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag}, Action: fnGet},
{Name: "getmeta", Usage: "Get function metadata", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag}, Action: fnGetMeta},
{Name: "update", Usage: "Update function source code", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag, fnEnvNameFlag, envNamespaceFlag, fnCodeFlag, fnSrcArchiveFlag, fnDeployArchiveFlag, fnEntryPointFlag, fnPkgNameFlag, pkgNamespaceFlag, fnBuildCmdFlag, fnForceFlag, minCpu, maxCpu, minMem, maxMem, minScale, maxScale, fnExecutorTypeFlag, targetcpu}, Action: fnUpdate},
{Name: "delete", Usage: "Delete function", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag}, Action: fnDelete},
// TODO : for fnList, i feel like it's nice to allow --fns all, to list functions across all namespaces for cluster admins, although, this is against ns isolation.
// so, in the future, if we end up using kubeconfig in fission cli and enforcing rolebindings to be created for users by admins etc, we can add this option at the time.
{Name: "list", Usage: "List all functions in a namespace if specified, else, list functions across all namespaces", Flags: []cli.Flag{fnNamespaceFlag}, Action: fnList},
{Name: "logs", Usage: "Display function logs", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag, fnPodFlag, fnFollowFlag, fnDetailFlag, fnLogDBTypeFlag, fnLogCountFlag}, Action: fnLogs},
{Name: "test", Usage: "Test a function", Flags: []cli.Flag{fnNameFlag, fnNamespaceFlag, fnEnvNameFlag, fnCodeFlag, fnSrcArchiveFlag, htMethodFlag, fnBodyFlag, fnHeaderFlag}, Action: fnTest},
}
// httptriggers
htNameFlag := cli.StringFlag{Name: "name", Usage: "HTTP Trigger name"}
htFnNameFlag := cli.StringFlag{Name: "function", Usage: "Function name"}
htSubcommands := []cli.Command{
{Name: "create", Aliases: []string{"add"}, Usage: "Create HTTP trigger", Flags: []cli.Flag{htMethodFlag, htUrlFlag, htFnNameFlag, specSaveFlag}, Action: htCreate},
{Name: "create", Aliases: []string{"add"}, Usage: "Create HTTP trigger", Flags: []cli.Flag{htMethodFlag, htUrlFlag, htFnNameFlag, fnNameFlag, fnNamespaceFlag, specSaveFlag}, Action: htCreate},
{Name: "get", Usage: "Get HTTP trigger", Flags: []cli.Flag{htMethodFlag, htUrlFlag}, Action: htGet},
{Name: "update", Usage: "Update HTTP trigger", Flags: []cli.Flag{htNameFlag, htFnNameFlag}, Action: htUpdate},
{Name: "delete", Usage: "Delete HTTP trigger", Flags: []cli.Flag{htNameFlag}, Action: htDelete},
{Name: "list", Usage: "List HTTP triggers", Flags: []cli.Flag{}, Action: htList},
{Name: "update", Usage: "Update HTTP trigger", Flags: []cli.Flag{htNameFlag, triggerNamespaceFlag, htFnNameFlag}, Action: htUpdate},
{Name: "delete", Usage: "Delete HTTP trigger", Flags: []cli.Flag{htNameFlag, triggerNamespaceFlag}, Action: htDelete},
{Name: "list", Usage: "List HTTP triggers", Flags: []cli.Flag{triggerNamespaceFlag}, Action: htList},
}
// timetriggers
@@ -170,11 +177,11 @@ func main() {
ttCronFlag := cli.StringFlag{Name: "cron", Usage: "Time Trigger cron spec ('0 30 * * *', '@every 5m', '@hourly')"}
ttFnNameFlag := cli.StringFlag{Name: "function", Usage: "Function name"}
ttSubcommands := []cli.Command{
{Name: "create", Aliases: []string{"add"}, Usage: "Create Time trigger", Flags: []cli.Flag{ttNameFlag, ttFnNameFlag, ttCronFlag, specSaveFlag}, Action: ttCreate},
{Name: "get", Usage: "Get Time trigger", Flags: []cli.Flag{}, Action: ttGet},
{Name: "update", Usage: "Update Time trigger", Flags: []cli.Flag{ttNameFlag, ttCronFlag, ttFnNameFlag}, Action: ttUpdate},
{Name: "delete", Usage: "Delete Time trigger", Flags: []cli.Flag{ttNameFlag}, Action: ttDelete},
{Name: "list", Usage: "List Time triggers", Flags: []cli.Flag{}, Action: ttList},
{Name: "create", Aliases: []string{"add"}, Usage: "Create Time trigger", Flags: []cli.Flag{ttNameFlag, ttFnNameFlag, fnNamespaceFlag, ttCronFlag, specSaveFlag}, Action: ttCreate},
{Name: "get", Usage: "Get Time trigger", Flags: []cli.Flag{triggerNamespaceFlag}, Action: ttGet},
{Name: "update", Usage: "Update Time trigger", Flags: []cli.Flag{ttNameFlag, triggerNamespaceFlag, ttCronFlag, ttFnNameFlag}, Action: ttUpdate},
{Name: "delete", Usage: "Delete Time trigger", Flags: []cli.Flag{ttNameFlag, triggerNamespaceFlag}, Action: ttDelete},
{Name: "list", Usage: "List Time triggers", Flags: []cli.Flag{triggerNamespaceFlag}, Action: ttList},
}
// Message queue trigger
@@ -185,11 +192,11 @@ func main() {
mqtRespTopicFlag := cli.StringFlag{Name: "resptopic", Usage: "Topic that the function response is sent on (optional; response discarded if unspecified)"}
mqtMsgContentType := cli.StringFlag{Name: "contenttype, c", Value: "application/json", Usage: "Content type of messages that publish to the topic (optional)"}
mqtSubcommands := []cli.Command{
{Name: "create", Aliases: []string{"add"}, Usage: "Create Message queue trigger", Flags: []cli.Flag{mqtNameFlag, mqtFnNameFlag, mqtMQTypeFlag, mqtTopicFlag, mqtRespTopicFlag, mqtMsgContentType, specSaveFlag}, Action: mqtCreate},
{Name: "get", Usage: "Get message queue trigger", Flags: []cli.Flag{}, Action: mqtGet},
{Name: "update", Usage: "Update message queue trigger", Flags: []cli.Flag{mqtNameFlag, mqtTopicFlag, mqtRespTopicFlag, mqtFnNameFlag, mqtMsgContentType}, Action: mqtUpdate},
{Name: "delete", Usage: "Delete message queue trigger", Flags: []cli.Flag{mqtNameFlag}, Action: mqtDelete},
{Name: "list", Usage: "List message queue triggers", Flags: []cli.Flag{mqtMQTypeFlag}, Action: mqtList},
{Name: "create", Aliases: []string{"add"}, Usage: "Create Message queue trigger", Flags: []cli.Flag{mqtNameFlag, mqtFnNameFlag, fnNamespaceFlag, mqtMQTypeFlag, mqtTopicFlag, mqtRespTopicFlag, mqtMsgContentType, specSaveFlag}, Action: mqtCreate},
{Name: "get", Usage: "Get message queue trigger", Flags: []cli.Flag{triggerNamespaceFlag}, Action: mqtGet},
{Name: "update", Usage: "Update message queue trigger", Flags: []cli.Flag{mqtNameFlag, triggerNamespaceFlag, mqtTopicFlag, mqtRespTopicFlag, mqtFnNameFlag, mqtMsgContentType}, Action: mqtUpdate},
{Name: "delete", Usage: "Delete message queue trigger", Flags: []cli.Flag{mqtNameFlag, triggerNamespaceFlag}, Action: mqtDelete},
{Name: "list", Usage: "List message queue triggers", Flags: []cli.Flag{mqtMQTypeFlag, triggerNamespaceFlag}, Action: mqtList},
}
// environments
@@ -202,11 +209,11 @@ func main() {
envTerminationGracePeriodFlag := cli.Int64Flag{Name: "graceperiod, period", Value: 360, Usage: "The grace time (in seconds) for pod to perform connection draining before termination (optional)"}
envVersionFlag := cli.IntFlag{Name: "version", Value: 1, Usage: "Environment API version (1 means v1 interface)"}
envSubcommands := []cli.Command{
{Name: "create", Aliases: []string{"add"}, Usage: "Add an environment", Flags: []cli.Flag{envNameFlag, envPoolsizeFlag, envImageFlag, envBuilderImageFlag, envBuildCmdFlag, minCpu, maxCpu, minMem, maxMem, envVersionFlag, envExternalNetworkFlag, envTerminationGracePeriodFlag, specSaveFlag}, Action: envCreate},
{Name: "get", Usage: "Get environment details", Flags: []cli.Flag{envNameFlag}, Action: envGet},
{Name: "update", Usage: "Update environment", Flags: []cli.Flag{envNameFlag, envPoolsizeFlag, envImageFlag, envBuilderImageFlag, envBuildCmdFlag, minCpu, maxCpu, minMem, maxMem, envExternalNetworkFlag, envTerminationGracePeriodFlag}, Action: envUpdate},
{Name: "delete", Usage: "Delete environment", Flags: []cli.Flag{envNameFlag}, Action: envDelete},
{Name: "list", Usage: "List all environments", Flags: []cli.Flag{}, Action: envList},
{Name: "create", Aliases: []string{"add"}, Usage: "Add an environment", Flags: []cli.Flag{envNameFlag, envNamespaceFlag, envPoolsizeFlag, envImageFlag, envBuilderImageFlag, envBuildCmdFlag, minCpu, maxCpu, minMem, maxMem, envVersionFlag, envExternalNetworkFlag, envTerminationGracePeriodFlag, specSaveFlag}, Action: envCreate},
{Name: "get", Usage: "Get environment details", Flags: []cli.Flag{envNameFlag, envNamespaceFlag}, Action: envGet},
{Name: "update", Usage: "Update environment", Flags: []cli.Flag{envNameFlag, envNamespaceFlag, envPoolsizeFlag, envImageFlag, envBuilderImageFlag, envBuildCmdFlag, minCpu, maxCpu, minMem, maxMem, envExternalNetworkFlag, envTerminationGracePeriodFlag}, Action: envUpdate},
{Name: "delete", Usage: "Delete environment", Flags: []cli.Flag{envNameFlag, envNamespaceFlag}, Action: envDelete},
{Name: "list", Usage: "List all environments", Flags: []cli.Flag{envNamespaceFlag}, Action: envList},
}
// watches
@@ -216,11 +223,11 @@ func main() {
wObjTypeFlag := cli.StringFlag{Name: "type", Usage: "Type of resource to watch (Pod, Service, etc.)"}
wLabelsFlag := cli.StringFlag{Name: "labels", Usage: "Label selector of the form a=b,c=d"}
wSubCommands := []cli.Command{
{Name: "create", Aliases: []string{"add"}, Usage: "Create a watch", Flags: []cli.Flag{wFnNameFlag, wNamespaceFlag, wObjTypeFlag, wLabelsFlag, specSaveFlag}, Action: wCreate},
{Name: "get", Usage: "Get details about a watch", Flags: []cli.Flag{wNameFlag}, Action: wGet},
{Name: "create", Aliases: []string{"add"}, Usage: "Create a watch", Flags: []cli.Flag{wFnNameFlag, fnNamespaceFlag, wNamespaceFlag, wObjTypeFlag, wLabelsFlag, specSaveFlag}, Action: wCreate},
{Name: "get", Usage: "Get details about a watch", Flags: []cli.Flag{wNameFlag, triggerNamespaceFlag}, Action: wGet},
// TODO add update flag when supported
{Name: "delete", Usage: "Delete watch", Flags: []cli.Flag{wNameFlag}, Action: wDelete},
{Name: "list", Usage: "List all watches", Flags: []cli.Flag{}, Action: wList},
{Name: "delete", Usage: "Delete watch", Flags: []cli.Flag{wNameFlag, triggerNamespaceFlag}, Action: wDelete},
{Name: "list", Usage: "List all watches", Flags: []cli.Flag{triggerNamespaceFlag}, Action: wList},
}
// packages
@@ -233,13 +240,13 @@ func main() {
pkgOutputFlag := cli.StringFlag{Name: "output, o", Usage: "Output filename to save archive content"}
pkgOrphanFlag := cli.BoolFlag{Name: "orphan", Usage: "orphan packages that are not referenced by any function"}
pkgSubCommands := []cli.Command{
{Name: "create", Usage: "Create new package", Flags: []cli.Flag{pkgEnvironmentFlag, pkgSrcArchiveFlag, pkgDeployArchiveFlag, pkgBuildCmdFlag}, Action: pkgCreate},
{Name: "update", Usage: "Update package", Flags: []cli.Flag{pkgNameFlag, pkgEnvironmentFlag, pkgSrcArchiveFlag, pkgDeployArchiveFlag, pkgBuildCmdFlag, pkgForceFlag}, Action: pkgUpdate},
{Name: "getsrc", Usage: "Get source archive content", Flags: []cli.Flag{pkgNameFlag, pkgOutputFlag}, Action: pkgSourceGet},
{Name: "getdeploy", Usage: "Get deployment archive content", Flags: []cli.Flag{pkgNameFlag, pkgOutputFlag}, Action: pkgDeployGet},
{Name: "info", Usage: "Show package information", Flags: []cli.Flag{pkgNameFlag}, Action: pkgInfo},
{Name: "list", Usage: "List all packages", Flags: []cli.Flag{pkgOrphanFlag}, Action: pkgList},
{Name: "delete", Usage: "Delete package", Flags: []cli.Flag{pkgNameFlag, pkgForceFlag, pkgOrphanFlag}, Action: pkgDelete},
{Name: "create", Usage: "Create new package", Flags: []cli.Flag{pkgNamespaceFlag, pkgEnvironmentFlag, envNamespaceFlag, pkgSrcArchiveFlag, pkgDeployArchiveFlag, pkgBuildCmdFlag}, Action: pkgCreate},
{Name: "update", Usage: "Update package", Flags: []cli.Flag{pkgNameFlag, pkgNamespaceFlag, pkgEnvironmentFlag, envNamespaceFlag, pkgSrcArchiveFlag, pkgDeployArchiveFlag, pkgBuildCmdFlag, pkgForceFlag}, Action: pkgUpdate},
{Name: "getsrc", Usage: "Get source archive content", Flags: []cli.Flag{pkgNameFlag, pkgNamespaceFlag, pkgOutputFlag}, Action: pkgSourceGet},
{Name: "getdeploy", Usage: "Get deployment archive content", Flags: []cli.Flag{pkgNameFlag, pkgNamespaceFlag, pkgOutputFlag}, Action: pkgDeployGet},
{Name: "info", Usage: "Show package information", Flags: []cli.Flag{pkgNameFlag, pkgNamespaceFlag}, Action: pkgInfo},
{Name: "list", Usage: "List all packages", Flags: []cli.Flag{pkgOrphanFlag, pkgNamespaceFlag}, Action: pkgList},
{Name: "delete", Usage: "Delete package", Flags: []cli.Flag{pkgNameFlag, pkgNamespaceFlag, pkgForceFlag, pkgOrphanFlag}, Action: pkgDelete},
}
// upgrades, data migrations
+8 -7
View File
@@ -23,6 +23,7 @@ import (
"net/http"
"github.com/urfave/cli"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/fission/fission"
"github.com/fission/fission/controller/client"
@@ -42,19 +43,19 @@ type (
)
func migrateDumpTPRResource(client *client.Client, filename string) {
pkgs, err := client.PackageList()
pkgs, err := client.PackageList(metav1.NamespaceAll)
checkErr(err, "dump packages")
fns, err := client.FunctionList()
fns, err := client.FunctionList(metav1.NamespaceAll)
checkErr(err, "dump functions")
httpTriggers, err := client.HTTPTriggerList()
httpTriggers, err := client.HTTPTriggerList(metav1.NamespaceAll)
checkErr(err, "dump http triggers")
envs, err := client.EnvironmentList()
envs, err := client.EnvironmentList(metav1.NamespaceAll)
checkErr(err, "dump environments")
watches, err := client.WatchList()
watches, err := client.WatchList(metav1.NamespaceAll)
checkErr(err, "dump watches")
timeTriggers, err := client.TimeTriggerList()
timeTriggers, err := client.TimeTriggerList(metav1.NamespaceAll)
checkErr(err, "dump time triggers")
mqTriggers, err := client.MessageQueueTriggerList(fission.MessageQueueTypeNats)
mqTriggers, err := client.MessageQueueTriggerList(fission.MessageQueueTypeNats, metav1.NamespaceAll)
checkErr(err, "dump message queue triggers")
tprResource := TPRResource{
+11 -4
View File
@@ -40,6 +40,7 @@ func mqtCreate(c *cli.Context) error {
if len(fnName) == 0 {
fatal("Need a function name to create a trigger, use --function")
}
fnNamespace := c.String("fnNamespace")
var mqType fission.MessageQueueType
switch c.String("mqtype") {
@@ -76,7 +77,7 @@ func mqtCreate(c *cli.Context) error {
mqt := &crd.MessageQueueTrigger{
Metadata: metav1.ObjectMeta{
Name: mqtName,
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
},
Spec: fission.MessageQueueTriggerSpec{
FunctionReference: fission.FunctionReference{
@@ -115,6 +116,8 @@ func mqtUpdate(c *cli.Context) error {
if len(mqtName) == 0 {
fatal("Need name of trigger, use --name")
}
mqtNs := c.String("triggerns")
topic := c.String("topic")
respTopic := c.String("resptopic")
fnName := c.String("function")
@@ -122,10 +125,12 @@ func mqtUpdate(c *cli.Context) error {
mqt, err := client.MessageQueueTriggerGet(&metav1.ObjectMeta{
Name: mqtName,
Namespace: metav1.NamespaceDefault,
Namespace: mqtNs,
})
checkErr(err, "get Time trigger")
// TODO : Find out if we can make a call to checkIfFunctionExists, in the same ns more importantly.
checkMQTopicAvailability(mqt.Spec.MessageQueueType, topic, respTopic)
updated := false
@@ -163,10 +168,11 @@ func mqtDelete(c *cli.Context) error {
if len(mqtName) == 0 {
fatal("Need name of trigger to delete, use --name")
}
mqtNs := c.String("triggerns")
err := client.MessageQueueTriggerDelete(&metav1.ObjectMeta{
Name: mqtName,
Namespace: metav1.NamespaceDefault,
Namespace: mqtNs,
})
checkErr(err, "delete trigger")
@@ -176,8 +182,9 @@ func mqtDelete(c *cli.Context) error {
func mqtList(c *cli.Context) error {
client := getClient(c.GlobalString("server"))
mqtNs := c.String("triggerns")
mqts, err := client.MessageQueueTriggerList(c.String("mqtype"))
mqts, err := client.MessageQueueTriggerList(c.String("mqtype"), mqtNs)
checkErr(err, "list message queue triggers")
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
+32 -23
View File
@@ -33,8 +33,8 @@ import (
"github.com/fission/fission/crd"
)
func getFunctionsByPackage(client *client.Client, pkgName string) ([]crd.Function, error) {
fnList, err := client.FunctionList()
func getFunctionsByPackage(client *client.Client, pkgName, pkgNamespace string) ([]crd.Function, error) {
fnList, err := client.FunctionList(pkgNamespace)
if err != nil {
return nil, err
}
@@ -65,11 +65,12 @@ func downloadStoragesvcURL(client *client.Client, fileUrl string) io.ReadCloser
func pkgCreate(c *cli.Context) error {
client := getClient(c.GlobalString("server"))
pkgNamespace := c.String("pkgNamespace")
envName := c.String("env")
if len(envName) == 0 {
fatal("Need --env argument.")
}
envNamespace := c.String("envNamespace")
srcArchiveName := c.String("src")
deployArchiveName := c.String("deploy")
buildcmd := c.String("buildcmd")
@@ -78,7 +79,7 @@ func pkgCreate(c *cli.Context) error {
fatal("Need --src to specify source archive, or use --deploy to specify deployment archive.")
}
meta := createPackage(client, envName, srcArchiveName, deployArchiveName, buildcmd, "")
meta := createPackage(client, pkgNamespace, envName, envNamespace, srcArchiveName, deployArchiveName, buildcmd, "")
fmt.Printf("Package '%v' created\n", meta.GetName())
return nil
@@ -91,9 +92,11 @@ func pkgUpdate(c *cli.Context) error {
if len(pkgName) == 0 {
fatal("Need --name argument.")
}
pkgNamespace := c.String("pkgNamespace")
force := c.Bool("f")
envName := c.String("env")
envNamespace := c.String("envNamespace")
srcArchiveName := c.String("src")
deployArchiveName := c.String("deploy")
buildcmd := c.String("buildcmd")
@@ -108,12 +111,12 @@ func pkgUpdate(c *cli.Context) error {
}
pkg, err := client.PackageGet(&metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Namespace: pkgNamespace,
Name: pkgName,
})
checkErr(err, "get package")
fnList, err := getFunctionsByPackage(client, pkg.Metadata.Name)
fnList, err := getFunctionsByPackage(client, pkg.Metadata.Name, pkg.Metadata.Namespace)
checkErr(err, "get function list")
if !force && len(fnList) > 1 {
@@ -121,7 +124,7 @@ func pkgUpdate(c *cli.Context) error {
}
newPkgMeta := updatePackage(client, pkg,
envName, srcArchiveName, deployArchiveName, buildcmd)
envName, envNamespace, srcArchiveName, deployArchiveName, buildcmd)
// update resource version of package reference of functions that shared the same package
for _, fn := range fnList {
@@ -135,7 +138,7 @@ func pkgUpdate(c *cli.Context) error {
return nil
}
func updatePackage(client *client.Client, pkg *crd.Package, envName,
func updatePackage(client *client.Client, pkg *crd.Package, envName, envNamespace,
srcArchiveName, deployArchiveName, buildcmd string) *metav1.ObjectMeta {
var srcArchiveMetadata, deployArchiveMetadata *fission.Archive
@@ -143,6 +146,7 @@ func updatePackage(client *client.Client, pkg *crd.Package, envName,
if len(envName) > 0 {
pkg.Spec.Environment.Name = envName
pkg.Spec.Environment.Namespace = envNamespace
needToBuild = true
}
@@ -183,11 +187,12 @@ func pkgSourceGet(c *cli.Context) error {
if len(pkgName) == 0 {
fatal("Need name of package, use --name")
}
pkgNamespace := c.String("pkgNamespace")
output := c.String("output")
pkg, err := client.PackageGet(&metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Namespace: pkgNamespace,
Name: pkgName,
})
if err != nil {
@@ -219,11 +224,12 @@ func pkgDeployGet(c *cli.Context) error {
if len(pkgName) == 0 {
fatal("Need name of package, use --name")
}
pkgNamespace := c.String("pkgNamespace")
output := c.String("output")
pkg, err := client.PackageGet(&metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Namespace: pkgNamespace,
Name: pkgName,
})
if err != nil {
@@ -255,9 +261,10 @@ func pkgInfo(c *cli.Context) error {
if len(pkgName) == 0 {
fatal("Need name of package, use --name")
}
pkgNamespace := c.String("pkgNamespace")
pkg, err := client.PackageGet(&metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Namespace: pkgNamespace,
Name: pkgName,
})
if err != nil {
@@ -278,8 +285,9 @@ func pkgList(c *cli.Context) error {
client := getClient(c.GlobalString("server"))
// option for the user to list all orphan packages (not referenced by any function)
listOrphans := c.Bool("orphan")
pkgNamespace := c.String("pkgNamespace")
pkgList, err := client.PackageList()
pkgList, err := client.PackageList(pkgNamespace)
if err != nil {
return err
}
@@ -288,7 +296,7 @@ func pkgList(c *cli.Context) error {
fmt.Fprintf(w, "%v\t%v\t%v\n", "NAME", "BUILD_STATUS", "ENV")
if listOrphans {
for _, pkg := range pkgList {
fnList, err := getFunctionsByPackage(client, pkg.Metadata.Name)
fnList, err := getFunctionsByPackage(client, pkg.Metadata.Name, pkg.Metadata.Namespace)
checkErr(err, fmt.Sprintf("get functions sharing package %s", pkg.Metadata.Name))
if len(fnList) == 0 {
fmt.Fprintf(w, "%v\t%v\t%v\n", pkg.Metadata.Name, pkg.Status.BuildStatus, pkg.Spec.Environment.Name)
@@ -306,18 +314,18 @@ func pkgList(c *cli.Context) error {
return nil
}
func deleteOrphanPkgs(client *client.Client) error {
pkgList, err := client.PackageList()
func deleteOrphanPkgs(client *client.Client, pkgNamespace string) error {
pkgList, err := client.PackageList(pkgNamespace)
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.Metadata.Name)
fnList, err := getFunctionsByPackage(client, pkg.Metadata.Name, pkgNamespace)
checkErr(err, fmt.Sprintf("get functions sharing package %s", pkg.Metadata.Name))
if len(fnList) == 0 {
err = deletePackage(client, pkg.Metadata.Name)
err = deletePackage(client, pkg.Metadata.Name, pkgNamespace)
if err != nil {
return err
}
@@ -326,9 +334,9 @@ func deleteOrphanPkgs(client *client.Client) error {
return nil
}
func deletePackage(client *client.Client, pkgName string) error {
func deletePackage(client *client.Client, pkgName string, pkgNamespace string) error {
return client.PackageDelete(&metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Namespace: pkgNamespace,
Name: pkgName,
})
}
@@ -337,6 +345,7 @@ func pkgDelete(c *cli.Context) error {
client := getClient(c.GlobalString("server"))
pkgName := c.String("name")
pkgNamespace := c.String("pkgNamespace")
deleteOrphans := c.Bool("orphan")
if len(pkgName) == 0 && !deleteOrphans {
@@ -352,25 +361,25 @@ func pkgDelete(c *cli.Context) error {
force := c.Bool("f")
_, err := client.PackageGet(&metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Namespace: pkgNamespace,
Name: pkgName,
})
checkErr(err, "find package")
fnList, err := getFunctionsByPackage(client, pkgName)
fnList, err := getFunctionsByPackage(client, pkgName, pkgNamespace)
if !force && len(fnList) > 0 {
fatal("Package is used by at least one function, use -f to force delete")
}
err = deletePackage(client, pkgName)
err = deletePackage(client, pkgName, pkgNamespace)
if err != nil {
return err
}
fmt.Printf("Package '%v' deleted\n", pkgName)
} else {
err := deleteOrphanPkgs(client)
err := deleteOrphanPkgs(client, pkgNamespace)
checkErr(err, "error deleting orphan packages")
fmt.Println("Orphan packages deleted")
}
+30 -11
View File
@@ -242,7 +242,8 @@ func (fr *FissionResources) validate() error {
// check references: both dangling refs + garbage
// packages -> archives
// functions -> packages
// functions -> environments [TODO]
// functions -> environments + shared environments between functions [TODO]
// functions -> secrets + configmaps (same ns) [TODO]
// triggers -> functions
// index archives
@@ -301,12 +302,30 @@ func (fr *FissionResources) validate() error {
for _, f := range fr.functions {
functions[mapKey(&f.Metadata)] = false
// check package ref from function
pkgMeta := &metav1.ObjectMeta{
Name: f.Spec.Package.PackageRef.Name,
Namespace: f.Spec.Package.PackageRef.Namespace,
}
if _, ok := packages[mapKey(pkgMeta)]; !ok {
// check package ref from function
packageRefExists := func() bool {
_, ok := packages[mapKey(pkgMeta)]
return ok
}
// check that the package referenced by each function is in the same ns as the function
packageRefInFuncNs := func(f *crd.Function) bool {
return f.Spec.Package.PackageRef.Namespace == f.Metadata.Namespace
}
if !packageRefInFuncNs(&f) {
result = multierror.Append(result, fmt.Errorf(
"%v: function '%v' references a package outside of its namespace %v/%v",
fr.sourceMap.locations["Function"][f.Metadata.Namespace][f.Metadata.Name],
f.Metadata.Name,
f.Spec.Package.PackageRef.Namespace,
f.Spec.Package.PackageRef.Name))
} else if !packageRefExists() {
result = multierror.Append(result, fmt.Errorf(
"%v: function '%v' references unknown package %v/%v",
fr.sourceMap.locations["Function"][f.Metadata.Namespace][f.Metadata.Name],
@@ -781,7 +800,7 @@ func applyArchives(fclient *client.Client, specDir string, fr *FissionResources)
// get list of packages, make content-indexed map of available archives
availableArchives := make(map[string]string) // (sha256 -> url)
pkgs, err := fclient.PackageList()
pkgs, err := fclient.PackageList(metav1.NamespaceAll)
if err != nil {
return err
}
@@ -1031,7 +1050,7 @@ func waitForPackageBuild(fclient *client.Client, pkg *crd.Package) (*crd.Package
func applyPackages(fclient *client.Client, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *resourceApplyStatus, error) {
// get list
allObjs, err := fclient.PackageList()
allObjs, err := fclient.PackageList(metav1.NamespaceAll)
if err != nil {
return nil, nil, err
}
@@ -1136,7 +1155,7 @@ func applyPackages(fclient *client.Client, fr *FissionResources, delete bool) (m
func applyFunctions(fclient *client.Client, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *resourceApplyStatus, error) {
// get list
allObjs, err := fclient.FunctionList()
allObjs, err := fclient.FunctionList(metav1.NamespaceAll)
if err != nil {
return nil, nil, err
}
@@ -1219,7 +1238,7 @@ func applyFunctions(fclient *client.Client, fr *FissionResources, delete bool) (
func applyEnvironments(fclient *client.Client, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *resourceApplyStatus, error) {
// get list
allObjs, err := fclient.EnvironmentList()
allObjs, err := fclient.EnvironmentList(metav1.NamespaceAll)
if err != nil {
return nil, nil, err
}
@@ -1302,7 +1321,7 @@ func applyEnvironments(fclient *client.Client, fr *FissionResources, delete bool
func applyHTTPTriggers(fclient *client.Client, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *resourceApplyStatus, error) {
// get list
allObjs, err := fclient.HTTPTriggerList()
allObjs, err := fclient.HTTPTriggerList(metav1.NamespaceAll)
if err != nil {
return nil, nil, err
}
@@ -1385,7 +1404,7 @@ func applyHTTPTriggers(fclient *client.Client, fr *FissionResources, delete bool
func applyKubernetesWatchTriggers(fclient *client.Client, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *resourceApplyStatus, error) {
// get list
allObjs, err := fclient.WatchList()
allObjs, err := fclient.WatchList(metav1.NamespaceAll)
if err != nil {
return nil, nil, err
}
@@ -1468,7 +1487,7 @@ func applyKubernetesWatchTriggers(fclient *client.Client, fr *FissionResources,
func applyTimeTriggers(fclient *client.Client, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *resourceApplyStatus, error) {
// get list
allObjs, err := fclient.TimeTriggerList()
allObjs, err := fclient.TimeTriggerList(metav1.NamespaceAll)
if err != nil {
return nil, nil, err
}
@@ -1551,7 +1570,7 @@ func applyTimeTriggers(fclient *client.Client, fr *FissionResources, delete bool
func applyMessageQueueTriggers(fclient *client.Client, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *resourceApplyStatus, error) {
// get list
allObjs, err := fclient.MessageQueueTriggerList("")
allObjs, err := fclient.MessageQueueTriggerList("", metav1.NamespaceAll)
if err != nil {
return nil, nil, err
}
+13 -4
View File
@@ -40,6 +40,8 @@ func ttCreate(c *cli.Context) error {
if len(fnName) == 0 {
fatal("Need a function name to create a trigger, use --function")
}
fnNamespace := c.String("fnNamespace")
cron := c.String("cron")
if len(cron) == 0 {
fatal("Need a cron spec like '0 30 * * *', '@every 1h30m', or '@hourly'; use --cron")
@@ -48,7 +50,7 @@ func ttCreate(c *cli.Context) error {
tt := &crd.TimeTrigger{
Metadata: metav1.ObjectMeta{
Name: name,
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
},
Spec: fission.TimeTriggerSpec{
Cron: cron,
@@ -84,10 +86,11 @@ func ttUpdate(c *cli.Context) error {
if len(ttName) == 0 {
fatal("Need name of trigger, use --name")
}
ttNs := c.String("triggerns")
tt, err := client.TimeTriggerGet(&metav1.ObjectMeta{
Name: ttName,
Namespace: metav1.NamespaceDefault,
Namespace: ttNs,
})
checkErr(err, "get time trigger")
@@ -97,6 +100,10 @@ func ttUpdate(c *cli.Context) error {
tt.Spec.Cron = newCron
updated = true
}
// TODO : During update, function has to be in the same ns as the trigger object
// but since we are not checking this for other triggers too, not sure if we need a check here.
fnName := c.String("function")
if len(fnName) > 0 {
tt.Spec.FunctionReference.Name = fnName
@@ -120,10 +127,11 @@ func ttDelete(c *cli.Context) error {
if len(ttName) == 0 {
fatal("Need name of trigger to delete, use --name")
}
ttNs := c.String("triggerns")
err := client.TimeTriggerDelete(&metav1.ObjectMeta{
Name: ttName,
Namespace: metav1.NamespaceDefault,
Namespace: ttNs,
})
checkErr(err, "delete trigger")
@@ -133,8 +141,9 @@ func ttDelete(c *cli.Context) error {
func ttList(c *cli.Context) error {
client := getClient(c.GlobalString("server"))
ttNs := c.String("triggerns")
tts, err := client.TimeTriggerList()
tts, err := client.TimeTriggerList(ttNs)
checkErr(err, "list Time triggers")
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
+7 -3
View File
@@ -36,6 +36,7 @@ func wCreate(c *cli.Context) error {
if len(fnName) == 0 {
fatal("Need a function name to create a watch, use --function")
}
fnNamespace := c.String("fnNamespace")
namespace := c.String("ns")
if len(namespace) == 0 {
@@ -64,7 +65,7 @@ func wCreate(c *cli.Context) error {
w := &crd.KubernetesWatchTrigger{
Metadata: metav1.ObjectMeta{
Name: watchName,
Namespace: metav1.NamespaceDefault,
Namespace: fnNamespace,
},
Spec: fission.KubernetesWatchTriggerSpec{
Namespace: namespace,
@@ -111,10 +112,11 @@ func wDelete(c *cli.Context) error {
if len(wName) == 0 {
fatal("Need name of watch to delete, use --name")
}
wNs := c.String("triggerns")
err := client.WatchDelete(&metav1.ObjectMeta{
Name: wName,
Namespace: metav1.NamespaceDefault,
Namespace: wNs,
})
checkErr(err, "delete watch")
@@ -125,7 +127,9 @@ func wDelete(c *cli.Context) error {
func wList(c *cli.Context) error {
client := getClient(c.GlobalString("server"))
ws, err := client.WatchList()
wNs := c.String("triggerns")
ws, err := client.WatchList(wNs)
checkErr(err, "list watches")
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)