Add --spec to package command (#1411)
This commit is contained in:
@@ -37,7 +37,7 @@ func Commands() *cobra.Command {
|
|||||||
flag.FnSpecializationTimeout, flag.FnExecutionTimeout,
|
flag.FnSpecializationTimeout, flag.FnExecutionTimeout,
|
||||||
|
|
||||||
// TODO retired pkg related flag from function cmd
|
// TODO retired pkg related flag from function cmd
|
||||||
flag.FnCode, flag.PkgSrcArchive, flag.PkgDeployArchive,
|
flag.PkgCode, flag.PkgSrcArchive, flag.PkgDeployArchive,
|
||||||
flag.HtUrl, flag.HtMethod,
|
flag.HtUrl, flag.HtMethod,
|
||||||
|
|
||||||
// flag for newdeploy to use.
|
// flag for newdeploy to use.
|
||||||
@@ -83,7 +83,7 @@ func Commands() *cobra.Command {
|
|||||||
flag.FnExecutorType, flag.FnSecret, flag.FnCfgMap,
|
flag.FnExecutorType, flag.FnSecret, flag.FnCfgMap,
|
||||||
flag.FnSpecializationTimeout, flag.FnExecutionTimeout,
|
flag.FnSpecializationTimeout, flag.FnExecutionTimeout,
|
||||||
|
|
||||||
flag.FnCode, flag.PkgSrcArchive, flag.PkgDeployArchive,
|
flag.PkgCode, flag.PkgSrcArchive, flag.PkgDeployArchive,
|
||||||
flag.FnBuildCmd, flag.PkgForce,
|
flag.FnBuildCmd, flag.PkgForce,
|
||||||
|
|
||||||
flag.RunTimeMinCPU, flag.RunTimeMaxCPU, flag.RunTimeMinMemory,
|
flag.RunTimeMinCPU, flag.RunTimeMaxCPU, flag.RunTimeMinMemory,
|
||||||
|
|||||||
@@ -116,16 +116,38 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
|
|
||||||
var pkgMetadata *metav1.ObjectMeta
|
var pkgMetadata *metav1.ObjectMeta
|
||||||
var envName string
|
var envName string
|
||||||
|
|
||||||
if len(pkgName) > 0 {
|
if len(pkgName) > 0 {
|
||||||
// use existing package
|
var pkg *fv1.Package
|
||||||
pkg, err := opts.client.PackageGet(&metav1.ObjectMeta{
|
|
||||||
Namespace: fnNamespace,
|
if toSpec {
|
||||||
Name: pkgName,
|
fr, err := spec.ReadSpecs(specDir)
|
||||||
})
|
if err != nil {
|
||||||
if err != nil {
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
return errors.Wrap(err, fmt.Sprintf("read package in '%v' in Namespace: %s. Package needs to be present in the same namespace as function", pkgName, fnNamespace))
|
}
|
||||||
|
obj := fr.SpecExists(&fv1.Package{
|
||||||
|
Metadata: metav1.ObjectMeta{
|
||||||
|
Name: pkgName,
|
||||||
|
Namespace: fnNamespace,
|
||||||
|
},
|
||||||
|
}, true, false)
|
||||||
|
if obj == nil {
|
||||||
|
return errors.Errorf("please create package %v spec file before referencing it", pkgName)
|
||||||
|
}
|
||||||
|
pkg = obj.(*fv1.Package)
|
||||||
|
pkgMetadata = &pkg.Metadata
|
||||||
|
} else {
|
||||||
|
// use existing package
|
||||||
|
pkg, err = opts.client.PackageGet(&metav1.ObjectMeta{
|
||||||
|
Namespace: fnNamespace,
|
||||||
|
Name: pkgName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(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
|
||||||
}
|
}
|
||||||
pkgMetadata = &pkg.Metadata
|
|
||||||
envName = pkg.Spec.Environment.Name
|
envName = pkg.Spec.Environment.Name
|
||||||
if envName != input.String(flagkey.FnEnvironmentName) {
|
if envName != input.String(flagkey.FnEnvironmentName) {
|
||||||
console.Warn("Function's environment is different than package's environment, package's environment will be used for creating function")
|
console.Warn("Function's environment is different than package's environment, package's environment will be used for creating function")
|
||||||
@@ -156,11 +178,11 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
srcArchiveFiles := input.StringSlice(flagkey.PkgSrcArchive)
|
srcArchiveFiles := input.StringSlice(flagkey.PkgSrcArchive)
|
||||||
var deployArchiveFiles []string
|
var deployArchiveFiles []string
|
||||||
noZip := false
|
noZip := false
|
||||||
code := input.String(flagkey.FnCode)
|
code := input.String(flagkey.PkgCode)
|
||||||
if len(code) == 0 {
|
if len(code) == 0 {
|
||||||
deployArchiveFiles = input.StringSlice(flagkey.PkgDeployArchive)
|
deployArchiveFiles = input.StringSlice(flagkey.PkgDeployArchive)
|
||||||
} else {
|
} else {
|
||||||
deployArchiveFiles = append(deployArchiveFiles, input.String(flagkey.FnCode))
|
deployArchiveFiles = append(deployArchiveFiles, input.String(flagkey.PkgCode))
|
||||||
noZip = true
|
noZip = true
|
||||||
}
|
}
|
||||||
// return error when both src & deploy archive are empty
|
// return error when both src & deploy archive are empty
|
||||||
|
|||||||
@@ -84,11 +84,11 @@ func (opts *UpdateSubCommand) complete(input cli.Input) error {
|
|||||||
|
|
||||||
var deployArchiveFiles []string
|
var deployArchiveFiles []string
|
||||||
codeFlag := false
|
codeFlag := false
|
||||||
code := input.String(flagkey.FnCode)
|
code := input.String(flagkey.PkgCode)
|
||||||
if len(code) == 0 {
|
if len(code) == 0 {
|
||||||
deployArchiveFiles = input.StringSlice(flagkey.PkgDeployArchive)
|
deployArchiveFiles = input.StringSlice(flagkey.PkgDeployArchive)
|
||||||
} else {
|
} else {
|
||||||
deployArchiveFiles = append(deployArchiveFiles, input.String(flagkey.FnCode))
|
deployArchiveFiles = append(deployArchiveFiles, input.String(flagkey.PkgCode))
|
||||||
codeFlag = true
|
codeFlag = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ func Commands() *cobra.Command {
|
|||||||
}
|
}
|
||||||
wrapper.SetFlags(createCmd, flag.FlagSet{
|
wrapper.SetFlags(createCmd, flag.FlagSet{
|
||||||
Required: []flag.Flag{flag.PkgEnvironment},
|
Required: []flag.Flag{flag.PkgEnvironment},
|
||||||
Optional: []flag.Flag{flag.PkgName, flag.PkgSrcArchive, flag.PkgDeployArchive,
|
Optional: []flag.Flag{flag.PkgName, flag.PkgCode, flag.PkgSrcArchive, flag.PkgDeployArchive,
|
||||||
flag.PkgBuildCmd, flag.NamespacePackage, flag.NamespaceEnvironment},
|
flag.PkgBuildCmd, flag.NamespacePackage, flag.NamespaceEnvironment, flag.SpecSave},
|
||||||
})
|
})
|
||||||
|
|
||||||
getSrcCmd := &cobra.Command{
|
getSrcCmd := &cobra.Command{
|
||||||
|
|||||||
@@ -62,7 +62,11 @@ func (opts *CreateSubCommand) do(input cli.Input) error {
|
|||||||
func (opts *CreateSubCommand) run(input cli.Input) error {
|
func (opts *CreateSubCommand) run(input cli.Input) error {
|
||||||
pkgName := input.String(flagkey.PkgName)
|
pkgName := input.String(flagkey.PkgName)
|
||||||
if len(pkgName) == 0 {
|
if len(pkgName) == 0 {
|
||||||
console.Warn(fmt.Sprintf("--%v will be soon marked as required flag, see 'help' for details", flagkey.HtName))
|
if input.Bool(flagkey.SpecSave) && len(input.String(flagkey.PkgName)) == 0 {
|
||||||
|
return errors.Errorf("--%v is necessary when creating spec file", flagkey.PkgName)
|
||||||
|
} else {
|
||||||
|
console.Warn(fmt.Sprintf("--%v will be soon marked as required flag, see 'help' for details", flagkey.HtName))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pkgNamespace := input.String(flagkey.NamespacePackage)
|
pkgNamespace := input.String(flagkey.NamespacePackage)
|
||||||
envName := input.String(flagkey.PkgEnvironment)
|
envName := input.String(flagkey.PkgEnvironment)
|
||||||
@@ -71,12 +75,27 @@ func (opts *CreateSubCommand) run(input cli.Input) error {
|
|||||||
deployArchiveFiles := input.StringSlice(flagkey.PkgDeployArchive)
|
deployArchiveFiles := input.StringSlice(flagkey.PkgDeployArchive)
|
||||||
buildcmd := input.String(flagkey.PkgBuildCmd)
|
buildcmd := input.String(flagkey.PkgBuildCmd)
|
||||||
|
|
||||||
|
noZip := false
|
||||||
|
code := input.String(flagkey.PkgCode)
|
||||||
|
if len(code) == 0 {
|
||||||
|
deployArchiveFiles = input.StringSlice(flagkey.PkgDeployArchive)
|
||||||
|
} else {
|
||||||
|
deployArchiveFiles = append(deployArchiveFiles, input.String(flagkey.PkgCode))
|
||||||
|
noZip = true
|
||||||
|
}
|
||||||
|
|
||||||
if len(srcArchiveFiles) == 0 && len(deployArchiveFiles) == 0 {
|
if len(srcArchiveFiles) == 0 && len(deployArchiveFiles) == 0 {
|
||||||
return errors.Errorf("need --%v or --%v flag", flagkey.PkgSrcArchive, flagkey.PkgDeployArchive)
|
return errors.Errorf("need --%v or --%v or --%v argument", flagkey.PkgCode, flagkey.PkgSrcArchive, flagkey.PkgDeployArchive)
|
||||||
|
}
|
||||||
|
|
||||||
|
var specDir, specFile string
|
||||||
|
if input.Bool(flagkey.SpecSave) {
|
||||||
|
specDir = util.GetSpecDir(input)
|
||||||
|
specFile = fmt.Sprintf("package-%v.yaml", pkgName)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := CreatePackage(input, opts.client, pkgName, pkgNamespace, envName, envNamespace,
|
_, err := CreatePackage(input, opts.client, pkgName, pkgNamespace, envName, envNamespace,
|
||||||
srcArchiveFiles, deployArchiveFiles, buildcmd, "", "", false)
|
srcArchiveFiles, deployArchiveFiles, buildcmd, specDir, specFile, noZip)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -138,14 +157,17 @@ func CreatePackage(input cli.Input, client *client.Client, pkgName string, pkgNa
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(specFile) > 0 {
|
if len(specFile) > 0 {
|
||||||
// if a package sith the same spec exists, don't create a new spec file
|
// if a package with the same spec exists, don't create a new spec file
|
||||||
fr, err := spec.ReadSpecs(util.GetSpecDir(input))
|
fr, err := spec.ReadSpecs(util.GetSpecDir(input))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error reading specs")
|
return nil, errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
if m := fr.SpecExists(pkg, false, true); m != nil {
|
|
||||||
fmt.Printf("Re-using previously created package %v\n", m.Name)
|
obj := fr.SpecExists(pkg, true, true)
|
||||||
return m, nil
|
if obj != nil {
|
||||||
|
pkg := obj.(*fv1.Package)
|
||||||
|
fmt.Printf("Re-using previously created package %v\n", pkg.Metadata.Name)
|
||||||
|
return &pkg.Metadata, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err = spec.SpecSave(*pkg, specFile)
|
err = spec.SpecSave(*pkg, specFile)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/dchest/uniuri"
|
"github.com/dchest/uniuri"
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
@@ -41,6 +42,17 @@ import (
|
|||||||
// upload the archive using client. noZip avoids zipping the
|
// upload the archive using client. noZip avoids zipping the
|
||||||
// includeFiles, but is ignored if there's more than one includeFile.
|
// includeFiles, but is ignored if there's more than one includeFile.
|
||||||
func CreateArchive(client *client.Client, includeFiles []string, noZip bool, specDir string, specFile string) (*fv1.Archive, error) {
|
func CreateArchive(client *client.Client, includeFiles []string, noZip bool, specDir string, specFile string) (*fv1.Archive, error) {
|
||||||
|
// get root dir
|
||||||
|
var rootDir string
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if len(specFile) > 0 {
|
||||||
|
rootDir, err = filepath.Abs(specDir + "/..")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error getting root directory of spec directory")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
errs := utils.MultiErrorWithFormat()
|
errs := utils.MultiErrorWithFormat()
|
||||||
fileURL := ""
|
fileURL := ""
|
||||||
|
|
||||||
@@ -57,9 +69,22 @@ func CreateArchive(client *client.Client, includeFiles []string, noZip bool, spe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get files from inputs as number of files decide next steps
|
// Get files from inputs as number of files decide next steps
|
||||||
|
absPath, err := filepath.Abs(path)
|
||||||
|
if err != nil {
|
||||||
|
errs = multierror.Append(errs, errors.Wrapf(err, "error converting path to the absolute path \"%v\"", path))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(absPath, rootDir) {
|
||||||
|
errs = multierror.Append(errs, errors.Errorf("The files (%v) should be put under the same parent directory (%v) of spec directory; otherwise, the archive will be empty when applying spec files", path, rootDir))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
path := filepath.Join(rootDir, path)
|
||||||
files, err := utils.FindAllGlobs([]string{path})
|
files, err := utils.FindAllGlobs([]string{path})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error finding all globs")
|
errs = multierror.Append(errs, errors.Wrap(err, "error finding all globs"))
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
@@ -89,9 +114,12 @@ func CreateArchive(client *client.Client, includeFiles []string, noZip bool, spe
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error reading specs")
|
return nil, errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
if m := fr.SpecExists(aus, false, true); m != nil {
|
|
||||||
fmt.Printf("Re-using previously created archive %v\n", m.Name)
|
obj := fr.SpecExists(aus, true, true)
|
||||||
aus.Name = m.Name
|
if obj != nil {
|
||||||
|
oldAus := obj.(*spectypes.ArchiveUploadSpec)
|
||||||
|
fmt.Printf("Re-using previously created archive %v\n", oldAus.Name)
|
||||||
|
aus.Name = oldAus.Name
|
||||||
} else {
|
} else {
|
||||||
// save the uploadspec
|
// save the uploadspec
|
||||||
err := spec.SpecSave(*aus, specFile)
|
err := spec.SpecSave(*aus, specFile)
|
||||||
|
|||||||
@@ -34,13 +34,9 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/cmd/spec/types"
|
"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/console"
|
||||||
"github.com/fission/fission/pkg/fission-cli/util"
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
"github.com/fission/fission/pkg/generator/encoder"
|
|
||||||
v1generator "github.com/fission/fission/pkg/generator/v1"
|
|
||||||
"github.com/fission/fission/pkg/utils"
|
"github.com/fission/fission/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var specDefaultEncoder = encoder.DefaultYAMLEncoder()
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FISSION_DEPLOYMENT_NAME_KEY = "fission-name"
|
FISSION_DEPLOYMENT_NAME_KEY = "fission-name"
|
||||||
FISSION_DEPLOYMENT_UID_KEY = "fission-uid"
|
FISSION_DEPLOYMENT_UID_KEY = "fission-uid"
|
||||||
@@ -129,8 +125,8 @@ func MapKey(m *metav1.ObjectMeta) string {
|
|||||||
return fmt.Sprintf("%v:%v", m.Namespace, m.Name)
|
return fmt.Sprintf("%v:%v", m.Namespace, m.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save saves object encoded value to spec file under given spec directory
|
// save saves object encoded value to spec file under given spec directory
|
||||||
func Save(data []byte, specDir string, specFile string) error {
|
func save(data []byte, specDir string, specFile string) error {
|
||||||
// verify
|
// verify
|
||||||
if _, err := os.Stat(filepath.Join(specDir, "fission-deployment-config.yaml")); os.IsNotExist(err) {
|
if _, err := os.Stat(filepath.Join(specDir, "fission-deployment-config.yaml")); os.IsNotExist(err) {
|
||||||
return errors.Wrap(err, "Couldn't find specs, run `fission spec init` first")
|
return errors.Wrap(err, "Couldn't find specs, run `fission spec init` first")
|
||||||
@@ -168,6 +164,7 @@ func Save(data []byte, specDir string, specFile string) error {
|
|||||||
|
|
||||||
// called from `fission * create --spec`
|
// called from `fission * create --spec`
|
||||||
func SpecSave(resource interface{}, specFile string) error {
|
func SpecSave(resource interface{}, specFile string) error {
|
||||||
|
var meta metav1.ObjectMeta
|
||||||
specDir := "specs"
|
specDir := "specs"
|
||||||
|
|
||||||
// make sure we're writing a known type
|
// make sure we're writing a known type
|
||||||
@@ -177,38 +174,44 @@ func SpecSave(resource interface{}, specFile string) error {
|
|||||||
case types.ArchiveUploadSpec:
|
case types.ArchiveUploadSpec:
|
||||||
typedres.Kind = "ArchiveUploadSpec"
|
typedres.Kind = "ArchiveUploadSpec"
|
||||||
data, err = yaml.Marshal(typedres)
|
data, err = yaml.Marshal(typedres)
|
||||||
|
meta = metav1.ObjectMeta{
|
||||||
|
Name: typedres.Name,
|
||||||
|
}
|
||||||
case fv1.Package:
|
case fv1.Package:
|
||||||
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
||||||
typedres.TypeMeta.Kind = "Package"
|
typedres.TypeMeta.Kind = "Package"
|
||||||
data, err = yaml.Marshal(typedres)
|
data, err = yaml.Marshal(typedres)
|
||||||
|
meta = typedres.Metadata
|
||||||
case fv1.Function:
|
case fv1.Function:
|
||||||
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
||||||
typedres.TypeMeta.Kind = "Function"
|
typedres.TypeMeta.Kind = "Function"
|
||||||
data, err = yaml.Marshal(typedres)
|
data, err = yaml.Marshal(typedres)
|
||||||
|
meta = typedres.Metadata
|
||||||
case fv1.Environment:
|
case fv1.Environment:
|
||||||
env := resource.(fv1.Environment)
|
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
||||||
var generator *v1generator.EnvironmentGenerator
|
typedres.TypeMeta.Kind = "Environment"
|
||||||
generator, err = v1generator.CreateEnvironmentGeneratorFromObj(&env)
|
data, err = yaml.Marshal(typedres)
|
||||||
if err != nil {
|
meta = typedres.Metadata
|
||||||
return err
|
|
||||||
}
|
|
||||||
data, err = generator.StructuredGenerate(specDefaultEncoder)
|
|
||||||
case fv1.HTTPTrigger:
|
case fv1.HTTPTrigger:
|
||||||
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
||||||
typedres.TypeMeta.Kind = "HTTPTrigger"
|
typedres.TypeMeta.Kind = "HTTPTrigger"
|
||||||
data, err = yaml.Marshal(typedres)
|
data, err = yaml.Marshal(typedres)
|
||||||
|
meta = typedres.Metadata
|
||||||
case fv1.KubernetesWatchTrigger:
|
case fv1.KubernetesWatchTrigger:
|
||||||
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
||||||
typedres.TypeMeta.Kind = "KubernetesWatchTrigger"
|
typedres.TypeMeta.Kind = "KubernetesWatchTrigger"
|
||||||
data, err = yaml.Marshal(typedres)
|
data, err = yaml.Marshal(typedres)
|
||||||
|
meta = typedres.Metadata
|
||||||
case fv1.MessageQueueTrigger:
|
case fv1.MessageQueueTrigger:
|
||||||
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
||||||
typedres.TypeMeta.Kind = "MessageQueueTrigger"
|
typedres.TypeMeta.Kind = "MessageQueueTrigger"
|
||||||
data, err = yaml.Marshal(typedres)
|
data, err = yaml.Marshal(typedres)
|
||||||
|
meta = typedres.Metadata
|
||||||
case fv1.TimeTrigger:
|
case fv1.TimeTrigger:
|
||||||
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
typedres.TypeMeta.APIVersion = fv1.CRD_VERSION
|
||||||
typedres.TypeMeta.Kind = "TimeTrigger"
|
typedres.TypeMeta.Kind = "TimeTrigger"
|
||||||
data, err = yaml.Marshal(typedres)
|
data, err = yaml.Marshal(typedres)
|
||||||
|
meta = typedres.Metadata
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("can't save resource %#v", resource)
|
return fmt.Errorf("can't save resource %#v", resource)
|
||||||
}
|
}
|
||||||
@@ -216,7 +219,28 @@ func SpecSave(resource interface{}, specFile string) error {
|
|||||||
return errors.Wrap(err, "Couldn't marshal YAML")
|
return errors.Wrap(err, "Couldn't marshal YAML")
|
||||||
}
|
}
|
||||||
|
|
||||||
return Save(data, specDir, specFile)
|
fr, err := ReadSpecs(specDir)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
|
}
|
||||||
|
|
||||||
|
exists, err := fr.existsInSpecs(resource)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
return errors.Errorf("same name resource (%v) already exists in namespace (%v)", meta.Name, meta.Namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = save(data, specDir, specFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
console.Info(fmt.Sprintf("Saving %v/%v to %v", meta.Namespace, meta.Name, specFile))
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateFunctionReference checks a function reference
|
// validateFunctionReference checks a function reference
|
||||||
@@ -263,32 +287,36 @@ func (fr *FissionResources) Validate(input cli.Input) error {
|
|||||||
for _, p := range fr.Packages {
|
for _, p := range fr.Packages {
|
||||||
packages[MapKey(&p.Metadata)] = false
|
packages[MapKey(&p.Metadata)] = false
|
||||||
|
|
||||||
// check archive refs from package
|
if strings.HasPrefix(p.Spec.Deployment.URL, ARCHIVE_URL_PREFIX) {
|
||||||
aname := strings.TrimPrefix(p.Spec.Source.URL, ARCHIVE_URL_PREFIX)
|
// check archive refs from package
|
||||||
if len(aname) > 0 {
|
aname := strings.TrimPrefix(p.Spec.Source.URL, ARCHIVE_URL_PREFIX)
|
||||||
if _, ok := archives[aname]; !ok {
|
if len(aname) > 0 {
|
||||||
result = multierror.Append(result, fmt.Errorf(
|
if _, ok := archives[aname]; !ok {
|
||||||
"%v: package '%v' references unknown source archive %v%v",
|
result = multierror.Append(result, fmt.Errorf(
|
||||||
fr.SourceMap.Locations["Package"][p.Metadata.Namespace][p.Metadata.Name],
|
"%v: package '%v' references unknown source archive %v%v",
|
||||||
p.Metadata.Name,
|
fr.SourceMap.Locations["Package"][p.Metadata.Namespace][p.Metadata.Name],
|
||||||
ARCHIVE_URL_PREFIX,
|
p.Metadata.Name,
|
||||||
aname))
|
ARCHIVE_URL_PREFIX,
|
||||||
} else {
|
aname))
|
||||||
archives[aname] = true
|
} else {
|
||||||
|
archives[aname] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aname = strings.TrimPrefix(p.Spec.Deployment.URL, ARCHIVE_URL_PREFIX)
|
if strings.HasPrefix(p.Spec.Deployment.URL, ARCHIVE_URL_PREFIX) {
|
||||||
if len(aname) > 0 {
|
aname := strings.TrimPrefix(p.Spec.Deployment.URL, ARCHIVE_URL_PREFIX)
|
||||||
if _, ok := archives[aname]; !ok {
|
if len(aname) > 0 {
|
||||||
result = multierror.Append(result, fmt.Errorf(
|
if _, ok := archives[aname]; !ok {
|
||||||
"%v: package '%v' references unknown deployment archive %v%v",
|
result = multierror.Append(result, fmt.Errorf(
|
||||||
fr.SourceMap.Locations["Package"][p.Metadata.Namespace][p.Metadata.Name],
|
"%v: package '%v' references unknown deployment archive %v%v",
|
||||||
p.Metadata.Name,
|
fr.SourceMap.Locations["Package"][p.Metadata.Namespace][p.Metadata.Name],
|
||||||
ARCHIVE_URL_PREFIX,
|
p.Metadata.Name,
|
||||||
aname))
|
ARCHIVE_URL_PREFIX,
|
||||||
} else {
|
aname))
|
||||||
archives[aname] = true
|
} else {
|
||||||
|
archives[aname] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +405,7 @@ func (fr *FissionResources) Validate(input cli.Input) error {
|
|||||||
ks := strings.Split(key, ":")
|
ks := strings.Split(key, ":")
|
||||||
namespace, name := ks[0], ks[1]
|
namespace, name := ks[0], ks[1]
|
||||||
if !referenced {
|
if !referenced {
|
||||||
result = multierror.Append(result, fmt.Errorf(
|
console.Warn(fmt.Sprintf(
|
||||||
"%v: package '%v' is not used in any function",
|
"%v: package '%v' is not used in any function",
|
||||||
fr.SourceMap.Locations["Package"][namespace][name],
|
fr.SourceMap.Locations["Package"][namespace][name],
|
||||||
name))
|
name))
|
||||||
@@ -431,7 +459,7 @@ func (fr *FissionResources) Validate(input cli.Input) error {
|
|||||||
}
|
}
|
||||||
// Unlike CLI can change the environment version silently,
|
// Unlike CLI can change the environment version silently,
|
||||||
// we have to warn the user to modify spec file when this takes place.
|
// we have to warn the user to modify spec file when this takes place.
|
||||||
if e.Spec.Version < 3 && e.Spec.Poolsize != 0 {
|
if e.Spec.Poolsize != 3 && e.Spec.Version < 3 {
|
||||||
console.Warn("Poolsize can only be configured when environment version equals to 3, default poolsize 3 will be used for creating environment pool.")
|
console.Warn("Poolsize can only be configured when environment version equals to 3, default poolsize 3 will be used for creating environment pool.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -591,7 +619,8 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
// Returns metadata if the given resource exists in the specs, nil
|
// Returns metadata if the given resource exists in the specs, nil
|
||||||
// otherwise. compareMetadata and compareSpec control how the
|
// otherwise. compareMetadata and compareSpec control how the
|
||||||
// equality check is performed.
|
// equality check is performed.
|
||||||
func (fr *FissionResources) SpecExists(resource interface{}, compareMetadata bool, compareSpec bool) *metav1.ObjectMeta {
|
// TODO: deprecated SpecExists
|
||||||
|
func (fr *FissionResources) SpecExists(resource interface{}, compareMetadata bool, compareSpec bool) interface{} {
|
||||||
switch typedres := resource.(type) {
|
switch typedres := resource.(type) {
|
||||||
case *types.ArchiveUploadSpec:
|
case *types.ArchiveUploadSpec:
|
||||||
for _, aus := range fr.ArchiveUploadSpecs {
|
for _, aus := range fr.ArchiveUploadSpecs {
|
||||||
@@ -604,7 +633,7 @@ func (fr *FissionResources) SpecExists(resource interface{}, compareMetadata boo
|
|||||||
reflect.DeepEqual(aus.ExcludeGlobs, typedres.ExcludeGlobs)) {
|
reflect.DeepEqual(aus.ExcludeGlobs, typedres.ExcludeGlobs)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return &metav1.ObjectMeta{Name: aus.Name}
|
return &aus
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case *fv1.Package:
|
case *fv1.Package:
|
||||||
@@ -615,7 +644,7 @@ func (fr *FissionResources) SpecExists(resource interface{}, compareMetadata boo
|
|||||||
if compareSpec && !reflect.DeepEqual(p.Spec, typedres.Spec) {
|
if compareSpec && !reflect.DeepEqual(p.Spec, typedres.Spec) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return &p.Metadata
|
return &p
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
@@ -625,6 +654,70 @@ func (fr *FissionResources) SpecExists(resource interface{}, compareMetadata boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fr *FissionResources) existsInSpecs(resource interface{}) (bool, error) {
|
||||||
|
switch typedres := resource.(type) {
|
||||||
|
case types.ArchiveUploadSpec:
|
||||||
|
for _, obj := range fr.ArchiveUploadSpecs {
|
||||||
|
if obj.Name == typedres.Name {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case fv1.Package:
|
||||||
|
for _, obj := range fr.Packages {
|
||||||
|
if obj.Metadata.Name == typedres.Metadata.Name &&
|
||||||
|
obj.Metadata.Namespace == typedres.Metadata.Namespace {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case fv1.Function:
|
||||||
|
for _, obj := range fr.Functions {
|
||||||
|
if obj.Metadata.Name == typedres.Metadata.Name &&
|
||||||
|
obj.Metadata.Namespace == typedres.Metadata.Namespace {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case fv1.Environment:
|
||||||
|
for _, obj := range fr.Environments {
|
||||||
|
if obj.Metadata.Name == typedres.Metadata.Name &&
|
||||||
|
obj.Metadata.Namespace == typedres.Metadata.Namespace {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case fv1.HTTPTrigger:
|
||||||
|
for _, obj := range fr.HttpTriggers {
|
||||||
|
if obj.Metadata.Name == typedres.Metadata.Name &&
|
||||||
|
obj.Metadata.Namespace == typedres.Metadata.Namespace {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case fv1.KubernetesWatchTrigger:
|
||||||
|
for _, obj := range fr.KubernetesWatchTriggers {
|
||||||
|
if obj.Metadata.Name == typedres.Metadata.Name &&
|
||||||
|
obj.Metadata.Namespace == typedres.Metadata.Namespace {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case fv1.MessageQueueTrigger:
|
||||||
|
for _, obj := range fr.MessageQueueTriggers {
|
||||||
|
if obj.Metadata.Name == typedres.Metadata.Name &&
|
||||||
|
obj.Metadata.Namespace == typedres.Metadata.Namespace {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case fv1.TimeTrigger:
|
||||||
|
for _, obj := range fr.TimeTriggers {
|
||||||
|
if obj.Metadata.Name == typedres.Metadata.Name &&
|
||||||
|
obj.Metadata.Namespace == typedres.Metadata.Namespace {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false, fmt.Errorf("unknown resource type %#v", typedres)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (loc Location) String() string {
|
func (loc Location) String() string {
|
||||||
return fmt.Sprintf("%v:%v", loc.Path, loc.Line)
|
return fmt.Sprintf("%v:%v", loc.Path, loc.Line)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ var (
|
|||||||
FnName = Flag{Type: String, Name: flagkey.FnName, Usage: "Function name"}
|
FnName = Flag{Type: String, Name: flagkey.FnName, Usage: "Function name"}
|
||||||
FnSpecializationTimeout = Flag{Type: Int, Name: flagkey.FnSpecializationTimeout, Aliases: []string{"st"}, Usage: "Timeout for executor to wait for function pod creation", DefaultValue: fv1.DefaultSpecializationTimeOut}
|
FnSpecializationTimeout = Flag{Type: Int, Name: flagkey.FnSpecializationTimeout, Aliases: []string{"st"}, Usage: "Timeout for executor to wait for function pod creation", DefaultValue: fv1.DefaultSpecializationTimeOut}
|
||||||
FnEnvName = Flag{Type: String, Name: flagkey.FnEnvironmentName, Usage: "Environment name for function"}
|
FnEnvName = Flag{Type: String, Name: flagkey.FnEnvironmentName, Usage: "Environment name for function"}
|
||||||
FnCode = Flag{Type: String, Name: flagkey.FnCode, Usage: "Local path or URL for single file source code"}
|
|
||||||
FnPkgName = Flag{Type: String, Name: flagkey.FnPackageName, Aliases: []string{"pkg"}, Usage: "Name of the existing package (--deploy and --src and --env will be ignored), should be in the same namespace as the function"}
|
FnPkgName = Flag{Type: String, Name: flagkey.FnPackageName, Aliases: []string{"pkg"}, Usage: "Name of the existing package (--deploy and --src and --env will be ignored), should be in the same namespace as the function"}
|
||||||
FnEntryPoint = Flag{Type: String, Name: flagkey.FnEntrypoint, Aliases: []string{"entry"}, Usage: "Entry point for environment v2 to load with"}
|
FnEntryPoint = Flag{Type: String, Name: flagkey.FnEntrypoint, Aliases: []string{"entry"}, Usage: "Entry point for environment v2 to load with"}
|
||||||
FnBuildCmd = Flag{Type: String, Name: flagkey.FnBuildCmd, Usage: "Package build command for builder to run with"}
|
FnBuildCmd = Flag{Type: String, Name: flagkey.FnBuildCmd, Usage: "Package build command for builder to run with"}
|
||||||
@@ -156,8 +155,9 @@ var (
|
|||||||
PkgOutput = Flag{Type: String, Name: flagkey.PkgOutput, Short: "o", Usage: "Output filename to save archive content"}
|
PkgOutput = Flag{Type: String, Name: flagkey.PkgOutput, Short: "o", Usage: "Output filename to save archive content"}
|
||||||
PkgStatus = Flag{Type: String, Name: flagkey.PkgStatus, Usage: `Filter packages by status`}
|
PkgStatus = Flag{Type: String, Name: flagkey.PkgStatus, Usage: `Filter packages by status`}
|
||||||
PkgOrphan = Flag{Type: Bool, Name: flagkey.PkgOrphan, Usage: "Orphan packages that are not referenced by any function"}
|
PkgOrphan = Flag{Type: Bool, Name: flagkey.PkgOrphan, Usage: "Orphan packages that are not referenced by any function"}
|
||||||
PkgDeployArchive = Flag{Type: StringSlice, Name: flagkey.PkgDeployArchive, Aliases: []string{"deploy"}, Usage: "Local path or URL for binary archive"}
|
PkgCode = Flag{Type: String, Name: flagkey.PkgCode, Usage: "URL or local path for single file source code"}
|
||||||
PkgSrcArchive = Flag{Type: StringSlice, Name: flagkey.PkgSrcArchive, Aliases: []string{"source", "src"}, Usage: "Local path or URL for source archive"}
|
PkgDeployArchive = Flag{Type: StringSlice, Name: flagkey.PkgDeployArchive, Aliases: []string{"deploy"}, Usage: "URL or local paths for binary archive"}
|
||||||
|
PkgSrcArchive = Flag{Type: StringSlice, Name: flagkey.PkgSrcArchive, Aliases: []string{"source", "src"}, Usage: "URL or local paths for source archive"}
|
||||||
|
|
||||||
SpecSave = Flag{Type: Bool, Name: flagkey.SpecSave, Usage: "Save to the spec directory instead of creating on cluster"}
|
SpecSave = Flag{Type: Bool, Name: flagkey.SpecSave, Usage: "Save to the spec directory instead of creating on cluster"}
|
||||||
SpecDir = Flag{Type: String, Name: flagkey.SpecDir, Usage: "Directory to store specs, defaults to ./specs"}
|
SpecDir = Flag{Type: String, Name: flagkey.SpecDir, Usage: "Directory to store specs, defaults to ./specs"}
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ const (
|
|||||||
FnName = resourceName
|
FnName = resourceName
|
||||||
FnSpecializationTimeout = "specializationtimeout"
|
FnSpecializationTimeout = "specializationtimeout"
|
||||||
FnEnvironmentName = "env"
|
FnEnvironmentName = "env"
|
||||||
FnCode = "code"
|
|
||||||
FnPackageName = "pkgname"
|
FnPackageName = "pkgname"
|
||||||
FnEntrypoint = "entrypoint"
|
FnEntrypoint = "entrypoint"
|
||||||
FnBuildCmd = "buildcmd"
|
FnBuildCmd = "buildcmd"
|
||||||
@@ -107,6 +106,7 @@ const (
|
|||||||
PkgName = resourceName
|
PkgName = resourceName
|
||||||
PkgForce = force
|
PkgForce = force
|
||||||
PkgEnvironment = "env"
|
PkgEnvironment = "env"
|
||||||
|
PkgCode = "code"
|
||||||
PkgSrcArchive = "sourcearchive"
|
PkgSrcArchive = "sourcearchive"
|
||||||
PkgDeployArchive = "deployarchive"
|
PkgDeployArchive = "deployarchive"
|
||||||
PkgBuildCmd = "buildcmd"
|
PkgBuildCmd = "buildcmd"
|
||||||
|
|||||||
Reference in New Issue
Block a user