Fix issues when specifying resources/scales during updating/creation process (#970)

This commit is contained in:
Ta-Ching Chen
2018-11-29 20:46:48 +08:00
committed by GitHub
parent 17cbc5baad
commit 7cedf8d580
7 changed files with 448 additions and 112 deletions
+8 -8
View File
@@ -361,23 +361,23 @@ func (deploy *NewDeploy) getResources(env *crd.Environment, fn *crd.Function) ap
resources.Limits = make(map[apiv1.ResourceName]resource.Quantity)
}
// Only override the once specified at function, rest default to values from env.
_, ok := fn.Spec.Resources.Requests[apiv1.ResourceCPU]
if ok {
val, ok := fn.Spec.Resources.Requests[apiv1.ResourceCPU]
if ok && !val.IsZero() {
resources.Requests[apiv1.ResourceCPU] = fn.Spec.Resources.Requests[apiv1.ResourceCPU]
}
_, ok = fn.Spec.Resources.Requests[apiv1.ResourceMemory]
if ok {
val, ok = fn.Spec.Resources.Requests[apiv1.ResourceMemory]
if ok && !val.IsZero() {
resources.Requests[apiv1.ResourceMemory] = fn.Spec.Resources.Requests[apiv1.ResourceMemory]
}
_, ok = fn.Spec.Resources.Limits[apiv1.ResourceCPU]
if ok {
val, ok = fn.Spec.Resources.Limits[apiv1.ResourceCPU]
if ok && !val.IsZero() {
resources.Limits[apiv1.ResourceCPU] = fn.Spec.Resources.Limits[apiv1.ResourceCPU]
}
_, ok = fn.Spec.Resources.Limits[apiv1.ResourceMemory]
if ok {
val, ok = fn.Spec.Resources.Limits[apiv1.ResourceMemory]
if ok && !val.IsZero() {
resources.Limits[apiv1.ResourceMemory] = fn.Spec.Resources.Limits[apiv1.ResourceMemory]
}
+24
View File
@@ -218,6 +218,10 @@ func envUpdate(c *cli.Context) error {
env.Spec.AllowAccessToExternalNetwork = envExternalNetwork
if c.IsSet("mincpu") || c.IsSet("maxcpu") || c.IsSet("minmemory") || c.IsSet("maxmemory") || c.IsSet("minscale") || c.IsSet("maxscale") {
log.Fatal("Updating resource limits/requests for existing environments is currently unsupported; re-create the environment instead.")
}
_, err = client.EnvironmentUpdate(env)
util.CheckErr(err, "update environment")
@@ -295,6 +299,7 @@ func getResourceReq(c *cli.Context, resources v1.ResourceRequirements) v1.Resour
}
var limitResources map[v1.ResourceName]resource.Quantity
if len(resources.Limits) == 0 {
limitResources = make(map[v1.ResourceName]resource.Quantity)
} else {
@@ -319,9 +324,28 @@ func getResourceReq(c *cli.Context, resources v1.ResourceRequirements) v1.Resour
limitResources[v1.ResourceMemory] = memLimit
}
limitCPU := limitResources[v1.ResourceCPU]
requestCPU := requestResources[v1.ResourceCPU]
if limitCPU.IsZero() && !requestCPU.IsZero() {
limitResources[v1.ResourceCPU] = requestCPU
} else if limitCPU.Cmp(requestCPU) < 0 {
log.Fatal(fmt.Sprintf("MinCPU (%v) cannot be greater than MaxCPU (%v)", requestCPU.String(), limitCPU.String()))
}
limitMem := limitResources[v1.ResourceMemory]
requestMem := requestResources[v1.ResourceMemory]
if limitMem.IsZero() && !requestMem.IsZero() {
limitResources[v1.ResourceMemory] = requestMem
} else if limitMem.Cmp(requestMem) < 0 {
log.Fatal(fmt.Sprintf("MinMemory (%v) cannot be greater than MaxMemory (%v)", requestMem.String(), limitMem.String()))
}
resources = v1.ResourceRequirements{
Requests: requestResources,
Limits: limitResources,
}
return resources
}
+98 -85
View File
@@ -41,6 +41,11 @@ import (
"github.com/fission/fission/fission/util"
)
const (
DEFAULT_MIN_SCALE = 1
DEFAULT_TARGET_CPU_PERCENTAGE = 80
)
func printPodLogs(c *cli.Context) error {
fnName := c.String("name")
if len(fnName) == 0 {
@@ -69,40 +74,91 @@ func printPodLogs(c *cli.Context) error {
return nil
}
func getInvokeStrategy(minScale int, maxScale int, executorType string, targetcpu int) fission.InvokeStrategy {
func getInvokeStrategy(c *cli.Context, existingInvokeStrategy *fission.InvokeStrategy) (strategy *fission.InvokeStrategy, err error) {
if maxScale == 0 {
maxScale = 1
}
var fnExecutor, newFnExecutor fission.ExecutorType
if minScale > maxScale {
log.Fatal("Maxscale must be higher than or equal to minscale")
}
var fnExecutor fission.ExecutorType
switch executorType {
switch c.String("executortype") {
case "":
fnExecutor = fission.ExecutorTypePoolmgr
fallthrough
case fission.ExecutorTypePoolmgr:
fnExecutor = fission.ExecutorTypePoolmgr
newFnExecutor = fission.ExecutorTypePoolmgr
case fission.ExecutorTypeNewdeploy:
fnExecutor = fission.ExecutorTypeNewdeploy
newFnExecutor = fission.ExecutorTypeNewdeploy
default:
log.Fatal("Executor type must be one of 'poolmgr' or 'newdeploy', defaults to 'poolmgr'")
return nil, errors.New("Executor type must be one of 'poolmgr' or 'newdeploy', defaults to 'poolmgr'")
}
// Right now a simple single case strategy implementation
// This will potentially get more sophisticated once we have more strategies in place
strategy := fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fnExecutor,
MinScale: minScale,
MaxScale: maxScale,
TargetCPUPercent: targetcpu,
},
if existingInvokeStrategy != nil {
fnExecutor = existingInvokeStrategy.ExecutionStrategy.ExecutorType
// override the executor type if user specified a new executor type
if c.IsSet("executortype") {
fnExecutor = newFnExecutor
}
} else {
fnExecutor = newFnExecutor
}
return strategy
if fnExecutor == fission.ExecutorTypePoolmgr {
if c.IsSet("targetcpu") || c.IsSet("minscale") || c.IsSet("maxscale") {
log.Fatal("To set target CPU or min/max scale for function, please specify \"--executortype newdeploy\"")
}
if c.IsSet("mincpu") || c.IsSet("maxcpu") || c.IsSet("minmemory") || c.IsSet("maxmemory") {
log.Warn("To limit CPU/Memory for function with executor type \"poolmgr\", please specify resources limits when creating environment")
}
strategy = &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypePoolmgr,
},
}
} else {
// set default value
targetCPU := DEFAULT_TARGET_CPU_PERCENTAGE
minScale := DEFAULT_MIN_SCALE
maxScale := minScale
if existingInvokeStrategy != nil && existingInvokeStrategy.ExecutionStrategy.ExecutorType == fission.ExecutorTypeNewdeploy {
minScale = existingInvokeStrategy.ExecutionStrategy.MinScale
maxScale = existingInvokeStrategy.ExecutionStrategy.MaxScale
targetCPU = existingInvokeStrategy.ExecutionStrategy.TargetCPUPercent
}
if c.IsSet("targetcpu") {
targetCPU = getTargetCPU(c)
}
if c.IsSet("minscale") {
minScale = c.Int("minscale")
}
if c.IsSet("maxscale") {
maxScale = c.Int("maxscale")
if maxScale <= 0 {
return nil, errors.New("Maxscale must be greater than 0")
}
}
if minScale > maxScale {
return nil, errors.New(fmt.Sprintf("Minscale provided: %v can not be greater than maxscale value %v", minScale, maxScale))
}
// Right now a simple single case strategy implementation
// This will potentially get more sophisticated once we have more strategies in place
strategy = &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fnExecutor,
MinScale: minScale,
MaxScale: maxScale,
TargetCPUPercent: targetCPU,
},
}
}
return strategy, nil
}
func getTargetCPU(c *cli.Context) int {
@@ -113,7 +169,7 @@ func getTargetCPU(c *cli.Context) int {
log.Fatal("TargetCPU must be a value between 1 - 100")
}
} else {
targetCPU = 80
targetCPU = DEFAULT_TARGET_CPU_PERCENTAGE
}
return targetCPU
}
@@ -150,12 +206,17 @@ func fnCreate(c *cli.Context) error {
entrypoint := c.String("entrypoint")
pkgName := c.String("pkg")
var pkgMetadata *metav1.ObjectMeta
var envName string
secretName := c.String("secret")
cfgMapName := c.String("configmap")
invokeStrategy, err := getInvokeStrategy(c, nil)
if err != nil {
log.Fatal(err)
}
resourceReq := getResourceReq(c, apiv1.ResourceRequirements{})
var pkgMetadata *metav1.ObjectMeta
var envName string
if len(pkgName) > 0 {
// use existing package
pkg, err := client.PackageGet(&metav1.ObjectMeta{
@@ -209,13 +270,6 @@ func fnCreate(c *cli.Context) error {
fmt.Printf("package '%v' created\n", pkgMetadata.Name)
}
invokeStrategy := getInvokeStrategy(c.Int("minscale"), c.Int("maxscale"), c.String("executortype"), getTargetCPU(c))
resourceReq := getResourceReq(c, apiv1.ResourceRequirements{})
if (c.IsSet("mincpu") || c.IsSet("maxcpu") || c.IsSet("minmemory") || c.IsSet("maxmemory")) &&
invokeStrategy.ExecutionStrategy.ExecutorType == fission.ExecutorTypePoolmgr {
log.Warn("CPU/Memory specified for function with pool manager executor will be ignored in favor of resources specified at environment")
}
var secrets []fission.SecretReference
var cfgmaps []fission.ConfigMapReference
@@ -274,7 +328,7 @@ func fnCreate(c *cli.Context) error {
Secrets: secrets,
ConfigMaps: cfgmaps,
Resources: resourceReq,
InvokeStrategy: invokeStrategy,
InvokeStrategy: *invokeStrategy,
},
}
@@ -486,6 +540,13 @@ func fnUpdate(c *cli.Context) error {
pkgName = function.Spec.Package.PackageRef.Name
}
strategy, err := getInvokeStrategy(c, &function.Spec.InvokeStrategy)
if err != nil {
log.Fatal(err)
}
function.Spec.InvokeStrategy = *strategy
function.Spec.Resources = getResourceReq(c, function.Spec.Resources)
pkg, err := client.PackageGet(&metav1.ObjectMeta{
Namespace: fnNamespace,
Name: pkgName,
@@ -534,54 +595,6 @@ func fnUpdate(c *cli.Context) error {
function.Spec.Environment.Namespace = pkg.Spec.Environment.Namespace
}
function.Spec.Resources = getResourceReq(c, function.Spec.Resources)
if c.IsSet("targetcpu") {
function.Spec.InvokeStrategy.ExecutionStrategy.TargetCPUPercent = getTargetCPU(c)
}
if c.IsSet("minscale") {
minscale := c.Int("minscale")
maxscale := c.Int("maxscale")
if c.IsSet("maxscale") && minscale > c.Int("maxscale") {
log.Fatal(fmt.Sprintf("Minscale's value %v can not be greater than maxscale value %v", minscale, maxscale))
}
if function.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType != fission.ExecutorTypePoolmgr &&
minscale > function.Spec.InvokeStrategy.ExecutionStrategy.MaxScale {
log.Fatal(fmt.Sprintf("Minscale provided: %v can not be greater than maxscale of existing function: %v", minscale,
function.Spec.InvokeStrategy.ExecutionStrategy.MaxScale))
}
function.Spec.InvokeStrategy.ExecutionStrategy.MinScale = minscale
}
if c.IsSet("maxscale") {
maxscale := c.Int("maxscale")
if maxscale < function.Spec.InvokeStrategy.ExecutionStrategy.MinScale {
log.Fatal(fmt.Sprintf("Function's minscale: %v can not be greater than maxscale provided: %v",
function.Spec.InvokeStrategy.ExecutionStrategy.MinScale, maxscale))
}
function.Spec.InvokeStrategy.ExecutionStrategy.MaxScale = maxscale
}
if c.IsSet("executortype") {
var fnExecutor fission.ExecutorType
switch c.String("executortype") {
case "":
fnExecutor = fission.ExecutorTypePoolmgr
case fission.ExecutorTypePoolmgr:
fnExecutor = fission.ExecutorTypePoolmgr
case fission.ExecutorTypeNewdeploy:
fnExecutor = fission.ExecutorTypeNewdeploy
default:
log.Fatal("Executor type must be one of 'poolmgr' or 'newdeploy', defaults to 'poolmgr'")
}
if (c.IsSet("mincpu") || c.IsSet("maxcpu") || c.IsSet("minmemory") || c.IsSet("maxmemory")) &&
fnExecutor == fission.ExecutorTypePoolmgr {
log.Warn("CPU/Memory specified for function with pool manager executor will be ignored in favor of resources specified at environment")
}
function.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType = fnExecutor
}
_, err = client.FunctionUpdate(function)
util.CheckErr(err, "update function")
+289
View File
@@ -0,0 +1,289 @@
package main
import (
"flag"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli"
"github.com/fission/fission"
)
func TestGetInvokeStrategy(t *testing.T) {
cases := []struct {
testArgs map[string]string
existingInvokeStrategy *fission.InvokeStrategy
expectedResult *fission.InvokeStrategy
expectError bool
}{
{
// case: use default executor poolmgr
testArgs: map[string]string{},
existingInvokeStrategy: nil,
expectedResult: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypePoolmgr,
},
},
expectError: false,
},
{
// case: executor type set to poolmgr
testArgs: map[string]string{"executortype": fission.ExecutorTypePoolmgr},
existingInvokeStrategy: nil,
expectedResult: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypePoolmgr,
},
},
expectError: false,
},
{
// case: executor type set to newdeploy
testArgs: map[string]string{"executortype": fission.ExecutorTypeNewdeploy},
existingInvokeStrategy: nil,
expectedResult: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypeNewdeploy,
MinScale: DEFAULT_MIN_SCALE,
MaxScale: DEFAULT_MIN_SCALE,
TargetCPUPercent: DEFAULT_TARGET_CPU_PERCENTAGE,
},
},
expectError: false,
},
{
// case: executor type change from poolmgr to newdeploy
testArgs: map[string]string{"executortype": fission.ExecutorTypeNewdeploy},
existingInvokeStrategy: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypePoolmgr,
},
},
expectedResult: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypeNewdeploy,
MinScale: DEFAULT_MIN_SCALE,
MaxScale: DEFAULT_MIN_SCALE,
TargetCPUPercent: DEFAULT_TARGET_CPU_PERCENTAGE,
},
},
expectError: false,
},
{
// case: executor type change from newdeploy to poolmgr
testArgs: map[string]string{"executortype": fission.ExecutorTypePoolmgr},
existingInvokeStrategy: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypeNewdeploy,
MinScale: DEFAULT_MIN_SCALE,
MaxScale: DEFAULT_MIN_SCALE,
TargetCPUPercent: DEFAULT_TARGET_CPU_PERCENTAGE,
},
},
expectedResult: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypePoolmgr,
},
},
expectError: false,
},
{
// case: minscale < maxscale
testArgs: map[string]string{
"executortype": fission.ExecutorTypeNewdeploy,
"minscale": "2",
"maxscale": "3",
},
existingInvokeStrategy: nil,
expectedResult: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypeNewdeploy,
MinScale: 2,
MaxScale: 3,
TargetCPUPercent: DEFAULT_TARGET_CPU_PERCENTAGE,
},
},
expectError: false,
},
{
// case: minscale > maxscale
testArgs: map[string]string{
"executortype": fission.ExecutorTypeNewdeploy,
"minscale": "5",
"maxscale": "3",
},
existingInvokeStrategy: nil,
expectedResult: nil,
expectError: true,
},
{
// case: maxscale not specified
testArgs: map[string]string{
"executortype": fission.ExecutorTypeNewdeploy,
"minscale": "5",
},
existingInvokeStrategy: nil,
expectedResult: nil,
expectError: true,
},
{
// case: minscale not specified
testArgs: map[string]string{
"executortype": fission.ExecutorTypeNewdeploy,
"maxscale": "3",
},
existingInvokeStrategy: nil,
expectedResult: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypeNewdeploy,
MinScale: DEFAULT_MIN_SCALE,
MaxScale: 3,
TargetCPUPercent: DEFAULT_TARGET_CPU_PERCENTAGE,
},
},
expectError: false,
},
{
// case: maxscale set to 0
testArgs: map[string]string{
"executortype": fission.ExecutorTypeNewdeploy,
"maxscale": "0",
},
existingInvokeStrategy: nil,
expectedResult: nil,
expectError: true,
},
{
// case: maxscale set to 9 when existing is 5
testArgs: map[string]string{
"executortype": fission.ExecutorTypeNewdeploy,
"maxscale": "9",
},
existingInvokeStrategy: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypeNewdeploy,
MinScale: 2,
MaxScale: 5,
TargetCPUPercent: DEFAULT_TARGET_CPU_PERCENTAGE,
},
},
expectedResult: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypeNewdeploy,
MinScale: 2,
MaxScale: 9,
TargetCPUPercent: DEFAULT_TARGET_CPU_PERCENTAGE,
},
},
expectError: false,
},
{
// case: change nothing for existing strategy
testArgs: map[string]string{
"executortype": fission.ExecutorTypeNewdeploy,
},
existingInvokeStrategy: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypeNewdeploy,
MinScale: 2,
MaxScale: 5,
TargetCPUPercent: DEFAULT_TARGET_CPU_PERCENTAGE,
},
},
expectedResult: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypeNewdeploy,
MinScale: 2,
MaxScale: 5,
TargetCPUPercent: DEFAULT_TARGET_CPU_PERCENTAGE,
},
},
expectError: false,
},
{
// case: set target cpu percentage
testArgs: map[string]string{
"executortype": fission.ExecutorTypeNewdeploy,
"targetcpu": "50",
},
existingInvokeStrategy: nil,
expectedResult: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypeNewdeploy,
MinScale: DEFAULT_MIN_SCALE,
MaxScale: DEFAULT_MIN_SCALE,
TargetCPUPercent: 50,
},
},
expectError: false,
},
{
// case: change target cpu percentage
testArgs: map[string]string{
"executortype": fission.ExecutorTypeNewdeploy,
"targetcpu": "20",
},
existingInvokeStrategy: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypeNewdeploy,
MinScale: 2,
MaxScale: 5,
TargetCPUPercent: 88,
},
},
expectedResult: &fission.InvokeStrategy{
StrategyType: fission.StrategyTypeExecution,
ExecutionStrategy: fission.ExecutionStrategy{
ExecutorType: fission.ExecutorTypeNewdeploy,
MinScale: 2,
MaxScale: 5,
TargetCPUPercent: 20,
},
},
expectError: false,
},
}
for i, c := range cases {
fmt.Printf("=== Test Case %v ===\n", i)
app := newCliApp()
set := flag.NewFlagSet("test-cmd", 0)
ctx := cli.NewContext(app, set, nil)
for k, v := range c.testArgs {
set.String(k, v, "")
ctx.Set(k, v)
}
strategy, err := getInvokeStrategy(ctx, c.existingInvokeStrategy)
if c.expectError {
assert.NotNil(t, err)
if err != nil {
fmt.Println(err)
}
} else {
assert.Nil(t, err)
assert.NoError(t, strategy.Validate(), fmt.Sprintf("Failed at test case %v", i))
assert.Equal(t, *c.expectedResult, *strategy)
}
}
}
+2 -2
View File
@@ -27,12 +27,12 @@ var (
)
func Fatal(msg interface{}) {
os.Stderr.WriteString(fmt.Sprintf("%v\n", msg))
os.Stderr.WriteString(fmt.Sprintf("Fatal error: %v\n", msg))
os.Exit(1)
}
func Warn(msg interface{}) {
os.Stderr.WriteString(fmt.Sprintf("[WARNING] %v\n", msg))
os.Stderr.WriteString(fmt.Sprintf("Warning: %v\n", msg))
}
func Info(msg interface{}) {
+13 -9
View File
@@ -38,6 +38,10 @@ func cliHook(c *cli.Context) error {
}
func main() {
newCliApp().Run(os.Args)
}
func newCliApp() *cli.App {
app := cli.NewApp()
app.Name = "fission"
app.Usage = "Serverless functions for Kubernetes"
@@ -74,13 +78,13 @@ func main() {
htUrlFlag := cli.StringFlag{Name: "url", Usage: "URL pattern (See gorilla/mux supported patterns)"}
// Resource & scale related flags (Used in env and function)
minCpu := cli.StringFlag{Name: "mincpu", Usage: "Minimum CPU to be assigned to pod (In millicore, minimum 1)"}
maxCpu := cli.StringFlag{Name: "maxcpu", Usage: "Maximum CPU to be assigned to pod (In millicore, minimum 1)"}
minMem := cli.StringFlag{Name: "minmemory", Usage: "Minimum memory to be assigned to pod (In megabyte)"}
maxMem := cli.StringFlag{Name: "maxmemory", Usage: "Maximum memory to be assigned to pod (In megabyte)"}
minScale := cli.StringFlag{Name: "minscale", Usage: "Minimum number of pods (Uses resource inputs to configure HPA)"}
maxScale := cli.StringFlag{Name: "maxscale", Usage: "Maximum number of pods (Uses resource inputs to configure HPA)"}
targetcpu := cli.IntFlag{Name: "targetcpu", Value: 80, Usage: "Target average CPU usage percentage across pods for scaling"}
minCpu := cli.IntFlag{Name: "mincpu", Usage: "Minimum CPU to be assigned to pod (In millicore, minimum 1)"}
maxCpu := cli.IntFlag{Name: "maxcpu", Usage: "Maximum CPU to be assigned to pod (In millicore, minimum 1)"}
minMem := cli.IntFlag{Name: "minmemory", Usage: "Minimum memory to be assigned to pod (In megabyte)"}
maxMem := cli.IntFlag{Name: "maxmemory", Usage: "Maximum memory to be assigned to pod (In megabyte)"}
minScale := cli.IntFlag{Name: "minscale", Usage: "Minimum number of pods (Uses resource inputs to configure HPA)"}
maxScale := cli.IntFlag{Name: "maxscale", Usage: "Maximum number of pods (Uses resource inputs to configure HPA)"}
targetcpu := cli.IntFlag{Name: "targetcpu", Usage: "Target average CPU usage percentage across pods for scaling"}
// functions
fnNameFlag := cli.StringFlag{Name: "name", Usage: "function name"}
@@ -102,7 +106,7 @@ func main() {
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", Usage: "Executor type for execution; one of 'poolmgr', 'newdeploy' defaults to 'poolmgr'"}
fnExecutorTypeFlag := cli.StringFlag{Name: "executortype", Value: fission.ExecutorTypePoolmgr, 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, fnNamespaceFlag, fnEnvNameFlag, envNamespaceFlag, specSaveFlag, fnCodeFlag, fnSrcArchiveFlag, fnDeployArchiveFlag, fnEntryPointFlag, fnBuildCmdFlag, fnPkgNameFlag, htUrlFlag, htMethodFlag, minCpu, maxCpu, minMem, maxMem, minScale, maxScale, fnExecutorTypeFlag, targetcpu, fnCfgMapFlag, fnSecretFlag}, Action: fnCreate},
@@ -309,7 +313,7 @@ func main() {
}
app.Before = cliHook
app.CommandNotFound = handleCommandNotFound
app.Run(os.Args)
return app
}
func handleCommandNotFound(ctx *cli.Context, subCommand string) {
+14 -8
View File
@@ -329,16 +329,22 @@ func (es ExecutionStrategy) Validate() error {
result = multierror.Append(result, MakeValidationErr(ErrorUnsupportedType, "ExecutionStrategy.ExecutorType", es.ExecutorType, "not a valid executor type"))
}
if es.MinScale < 0 {
result = multierror.Append(result, MakeValidationErr(ErrorInvalidValue, "ExecutionStrategy.MinScale", es.MinScale, "minimum scale must be greater or equal to 0"))
}
if es.ExecutorType == ExecutorTypeNewdeploy {
if es.MinScale < 0 {
result = multierror.Append(result, MakeValidationErr(ErrorInvalidValue, "ExecutionStrategy.MinScale", es.MinScale, "minimum scale must be greater or equal to 0"))
}
if es.MaxScale < es.MinScale {
result = multierror.Append(result, MakeValidationErr(ErrorInvalidValue, "ExecutionStrategy.MaxScale", es.MaxScale, "maximum scale must be greater or equal to minimum scale"))
}
if es.MaxScale <= 0 {
result = multierror.Append(result, MakeValidationErr(ErrorInvalidValue, "ExecutionStrategy.MaxScale", es.MaxScale, "maximum scale must be greater than 0"))
}
if es.TargetCPUPercent <= 0 || es.TargetCPUPercent > 100 {
result = multierror.Append(result, MakeValidationErr(ErrorInvalidValue, "ExecutionStrategy.TargetCPUPercent", es.TargetCPUPercent, "TargetCPUPercent must be a value between 1 - 100"))
if es.MaxScale < es.MinScale {
result = multierror.Append(result, MakeValidationErr(ErrorInvalidValue, "ExecutionStrategy.MaxScale", es.MaxScale, "maximum scale must be greater or equal to minimum scale"))
}
if es.TargetCPUPercent <= 0 || es.TargetCPUPercent > 100 {
result = multierror.Append(result, MakeValidationErr(ErrorInvalidValue, "ExecutionStrategy.TargetCPUPercent", es.TargetCPUPercent, "TargetCPUPercent must be a value between 1 - 100"))
}
}
return result.ErrorOrNil()