mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-18 20:17:04 +00:00
Autoscaler for appfile (#510)
* Autoscaler for appfile completed spec.extension.template to support autoscale in cli and appfile * add alias name to cpuRequest in Cli for deploying webservice
This commit is contained in:
@@ -85,6 +85,7 @@ type Parameter struct {
|
||||
Default interface{} `json:"default,omitempty"`
|
||||
Usage string `json:"usage,omitempty"`
|
||||
Type cue.Kind `json:"type,omitempty"`
|
||||
Alias string `json:"alias,omitempty"`
|
||||
}
|
||||
|
||||
// ConvertTemplateJSON2Object convert spec.extension to object
|
||||
@@ -105,6 +106,10 @@ func ConvertTemplateJSON2Object(in *runtime.RawExtension) (Capability, error) {
|
||||
}
|
||||
|
||||
func SetFlagBy(flags *pflag.FlagSet, v Parameter) {
|
||||
name := v.Name
|
||||
if v.Alias != "" {
|
||||
name = v.Alias
|
||||
}
|
||||
switch v.Type {
|
||||
case cue.IntKind:
|
||||
var vv int64
|
||||
@@ -118,11 +123,11 @@ func SetFlagBy(flags *pflag.FlagSet, v Parameter) {
|
||||
case float64:
|
||||
vv = int64(val)
|
||||
}
|
||||
flags.Int64P(v.Name, v.Short, vv, v.Usage)
|
||||
flags.Int64P(name, v.Short, vv, v.Usage)
|
||||
case cue.StringKind:
|
||||
flags.StringP(v.Name, v.Short, v.Default.(string), v.Usage)
|
||||
flags.StringP(name, v.Short, v.Default.(string), v.Usage)
|
||||
case cue.BoolKind:
|
||||
flags.BoolP(v.Name, v.Short, v.Default.(bool), v.Usage)
|
||||
flags.BoolP(name, v.Short, v.Default.(bool), v.Usage)
|
||||
case cue.NumberKind, cue.FloatKind:
|
||||
var vv float64
|
||||
switch val := v.Default.(type) {
|
||||
@@ -135,7 +140,7 @@ func SetFlagBy(flags *pflag.FlagSet, v Parameter) {
|
||||
case float64:
|
||||
vv = val
|
||||
}
|
||||
flags.Float64P(v.Name, v.Short, vv, v.Usage)
|
||||
flags.Float64P(name, v.Short, vv, v.Usage)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ metadata:
|
||||
annotations:
|
||||
definition.oam.dev/apiVersion: standard.oam.dev/v1alpha1
|
||||
definition.oam.dev/kind: Autoscaler
|
||||
definition.oam.dev/description: "Automatically scale workloads by cron or resource utilization"
|
||||
definition.oam.dev/description: "Automatically scale workloads"
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- webservice
|
||||
@@ -18,32 +18,56 @@ spec:
|
||||
extension:
|
||||
template: |
|
||||
output: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Autoscaler"
|
||||
spec: {
|
||||
minReplicas: parameter.minReplicas
|
||||
maxReplicas: parameter.maxReplicas
|
||||
triggers: [{
|
||||
name: parameter.name
|
||||
type: parameter.type
|
||||
condition: {
|
||||
startAt: parameter.startAt
|
||||
duration: parameter.duration
|
||||
days: parameter.days
|
||||
replicas: parameter.replicas
|
||||
timezone: parameter.timezone
|
||||
}
|
||||
}, ...]
|
||||
}
|
||||
}
|
||||
parameter: {
|
||||
minReplicas: *1 | int
|
||||
maxReplicas: *4 | int
|
||||
name: *"" | string
|
||||
type: *"cron" | string
|
||||
startAt: string
|
||||
duration: string
|
||||
days: string
|
||||
replicas: *"2" | string
|
||||
timezone: *"Asia/Shanghai" | string
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Autoscaler"
|
||||
spec: {
|
||||
minReplicas: parameter.min
|
||||
maxReplicas: parameter.max
|
||||
if parameter["cpu"] != _|_ && parameter["cron"] != _|_ {
|
||||
triggers: [cpuScaler, cronScaler]
|
||||
}
|
||||
if parameter["cpu"] != _|_ && parameter["cron"] == _|_ {
|
||||
triggers: [cpuScaler]
|
||||
}
|
||||
if parameter["cpu"] == _|_ && parameter["cron"] != _|_ {
|
||||
triggers: [cronScaler]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cpuScaler: {
|
||||
type: "cpu"
|
||||
condition: {
|
||||
type: "Utilization"
|
||||
if parameter["cpu"] != _|_ {
|
||||
value: parameter.cpu
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cronScaler: {
|
||||
type: "cron"
|
||||
if parameter["cron"] != _|_ {
|
||||
condition: parameter.cron
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=minimal replicas of the workload
|
||||
min: int
|
||||
// +usage=maximal replicas of the workload
|
||||
max: int
|
||||
// +usage=specify the value for CPU utilization, like 80, which means 80%
|
||||
cpu?: string
|
||||
// +usage=just for `appfile`, not available for Cli usage
|
||||
cron?: {
|
||||
startAt: string
|
||||
duration: string
|
||||
// +usage=several workdays or weekends, like "Monday, Tuesday"
|
||||
days: string
|
||||
replicas: string
|
||||
// +usage=timezone, like "America/Seattle"
|
||||
timezone: string
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,17 @@ spec:
|
||||
ports: [{
|
||||
containerPort: parameter.port
|
||||
}]
|
||||
|
||||
if parameter["cpuRequests"] != _|_ {
|
||||
resources: {
|
||||
limits:
|
||||
cpu: parameter.cpuRequests
|
||||
requests:
|
||||
cpu: parameter.cpuRequests
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,5 +84,8 @@ spec:
|
||||
}
|
||||
}
|
||||
}]
|
||||
// +usage=CPU core requests for the workload
|
||||
// +alias=cpu-requests
|
||||
cpuRequests?: string
|
||||
}
|
||||
|
||||
|
||||
@@ -26,5 +26,5 @@ data:
|
||||
"urL": "https://kedacore.github.io/charts",
|
||||
"name": "keda",
|
||||
"namespace": "keda",
|
||||
"version": "2.0.0-beta1.2"
|
||||
"version": "2.0.0-rc3"
|
||||
}
|
||||
|
||||
@@ -1,65 +1,235 @@
|
||||
# Automatically scale workload by cron or resource utilization
|
||||
# Automatically scale workloads by resource utilization metrics and cron
|
||||
|
||||
## Prerequisites
|
||||
- [ ] [KEDA v2.0 Beta](https://keda.sh/blog/keda-2.0-beta/)
|
||||
|
||||
KEDA will be automatically deployed during vela installation, so just run the following command.
|
||||
```shell
|
||||
$ vela install
|
||||
```
|
||||
|
||||
## Scale an application
|
||||
Contents:
|
||||
- [Scale by CPU resource utilization metrics](#Scale by CPU resource utilization metrics)
|
||||
- [Scale workload by cron](#Scale workload by cron)
|
||||
|
||||
## Scale by CPU resource utilization metrics
|
||||
Introduce how to automatically scale workloads by resource utilization metrics in Cli. Currently, only cpu utilization
|
||||
is supported.
|
||||
|
||||
- Deploy an application
|
||||
|
||||
Run the following command to deploy application `helloworld`.
|
||||
|
||||
```
|
||||
$ vela svc deploy frontend -t webservice -a helloworld --image nginx:1.9.2 --port 80
|
||||
$ vela svc deploy frontend -t webservice -a helloworld --image nginx:1.9.2 --port 80 --cpu-requests=0.05
|
||||
App helloworld deployed
|
||||
```
|
||||
|
||||
Check the replicas of Deployment `frontend` which is deployed by workload webservice `helloworld` and there is one replica.
|
||||
|
||||
(TODO: The command below needs to be replaced with `vela show` to check the replicas.)
|
||||
```
|
||||
$ kubectl get deploy frontend
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
frontend 1/1 1 1 2m52s
|
||||
```
|
||||
By default, the replicas of the workload webservice `helloworld` is.
|
||||
|
||||
- Scale the application by `cron`
|
||||
- Scale the application by CPU utilization metrics
|
||||
```
|
||||
$ vela autoscale helloworld --svc frontend --minReplicas 1 --maxReplicas 4 --replicas 2 --name cron-test --startAt 21:00 --duration 2h --days "Monday, Tuesday"
|
||||
$ vela autoscale helloworld --svc frontend --min 1 --max 5 --cpu 5
|
||||
Adding autoscale for app frontend
|
||||
⠋ Deploying ...
|
||||
⠋ Checking Status ...
|
||||
✅ Application Deployed Successfully!
|
||||
- Name: frontend
|
||||
Type: webservice
|
||||
HEALTHY Ready: 1/1
|
||||
Last Deployment:
|
||||
Created at: 2020-11-03 20:53:50 +0800 CST
|
||||
Updated at: 2020-11-03T21:01:20+08:00
|
||||
Traits:
|
||||
- autoscale:
|
||||
maxReplicas=4
|
||||
minReplicas=1
|
||||
replicas=2
|
||||
startAt=21:00
|
||||
timezone=Asia/Shanghai
|
||||
days=Monday, Tuesday
|
||||
name=cron-test
|
||||
type=cron
|
||||
duration=2h
|
||||
- ✅ autoscale: type: cpu minReplicas: 1 maxReplicas: 5 CPUUtilization(target/current): 5%/0% replicas: 0
|
||||
Last Deployment:
|
||||
Created at: 2020-11-06 16:10:54 +0800 CST
|
||||
Updated at: 2020-11-06T16:19:04+08:0
|
||||
```
|
||||
|
||||
The time is `21:07` which is in the active period of the trait which started at `21:00` and the duration is two hours.
|
||||
Check the replicas of Deployment `frontend` again, it has been scaled to 2.
|
||||
- Access the application with heavy requests
|
||||
|
||||
```
|
||||
$ kubectl get deploy
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
frontend 2/2 2 2 8m42s
|
||||
$ vela port-forward helloworld 80
|
||||
Forwarding from 127.0.0.1:80 -> 80
|
||||
Forwarding from [::1]:80 -> 80
|
||||
|
||||
Forward successfully! Opening browser ...
|
||||
Handling connection for 80
|
||||
Handling connection for 80
|
||||
Handling connection for 80
|
||||
Handling connection for 80
|
||||
```
|
||||
|
||||
On your macOS, you might need to add `sudo` ahead of the command.
|
||||
|
||||
- Use Apache HTTP server benchmarking tool `ab` to access the application.
|
||||
|
||||
```
|
||||
$ ab -n 10000 -c 200 http://127.0.0.1/
|
||||
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
|
||||
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
|
||||
Licensed to The Apache Software Foundation, http://www.apache.org/
|
||||
|
||||
Benchmarking 127.0.0.1 (be patient)
|
||||
Completed 1000 requests
|
||||
```
|
||||
|
||||
Monitor the replicas of the workload, and its replicas gradually increase from one to four.
|
||||
```
|
||||
$ vela status helloworld --svc frontend
|
||||
About:
|
||||
|
||||
Name: helloworld
|
||||
Namespace: default
|
||||
Created at: 2020-11-05 20:07:21.830118 +0800 CST
|
||||
Updated at: 2020-11-05 20:50:42.664725 +0800 CST
|
||||
|
||||
Services:
|
||||
|
||||
- Name: frontend
|
||||
Type: webservice
|
||||
HEALTHY Ready: 1/1
|
||||
Traits:
|
||||
- ✅ autoscale: type: cpu minReplicas: 1 maxReplicas: 5 CPUUtilization(target/current): 5%/10% replicas: 2
|
||||
Last Deployment:
|
||||
Created at: 2020-11-05 20:07:23 +0800 CST
|
||||
Updated at: 2020-11-05T20:50:42+08:00
|
||||
```
|
||||
|
||||
```
|
||||
$ vela status helloworld --svc frontend
|
||||
About:
|
||||
|
||||
Name: helloworld
|
||||
Namespace: default
|
||||
Created at: 2020-11-05 20:07:21.830118 +0800 CST
|
||||
Updated at: 2020-11-05 20:50:42.664725 +0800 CST
|
||||
|
||||
Services:
|
||||
|
||||
- Name: frontend
|
||||
Type: webservice
|
||||
HEALTHY Ready: 1/1
|
||||
Traits:
|
||||
- ✅ autoscale: type: cpu minReplicas: 1 maxReplicas: 5 CPUUtilization(target/current): 5%/14% replicas: 4
|
||||
Last Deployment:
|
||||
Created at: 2020-11-05 20:07:23 +0800 CST
|
||||
Updated at: 2020-11-05T20:50:42+08:00
|
||||
```
|
||||
|
||||
Stop `ab` tool, and the replicas will decrease to one eventually.
|
||||
|
||||
|
||||
## Scale workload by cron
|
||||
Introduce how to automatically scale workloads by cron in Appfile.
|
||||
|
||||
- Prepare Appfile
|
||||
Follow the instructions of [appfile](./devex/appfile.md) to prepare the `vela.yaml` as below.
|
||||
```
|
||||
name: testapp
|
||||
|
||||
services:
|
||||
express-server:
|
||||
# this image will be used in both build and deploy steps
|
||||
image: zzxwill/kubevela-appfile-demo:v1
|
||||
|
||||
build:
|
||||
# Here more runtime specific build templates will be supported, like NodeJS, Go, Python, Ruby.
|
||||
docker:
|
||||
file: Dockerfile
|
||||
context: .
|
||||
|
||||
cmd: ["node", "server.js"]
|
||||
port: 8080
|
||||
|
||||
autoscale:
|
||||
minReplicas: 1
|
||||
maxReplicas: 4
|
||||
cron:
|
||||
startAt: "14:00"
|
||||
duration: "2h"
|
||||
days: "Monday, Thursday"
|
||||
replicas: "2"
|
||||
timezone: "America/Seattle"
|
||||
```
|
||||
|
||||
- Deploy an application
|
||||
Run the following command to deploy the application defined in `vela.yaml`.
|
||||
|
||||
```
|
||||
$ vela up
|
||||
Parsing vela.yaml ...
|
||||
Loading templates ...
|
||||
|
||||
Building service (express-server)...
|
||||
#2 [internal] load build definition from Dockerfile
|
||||
#2 sha256:c25a03ff9861be1da16a316055d11b83778efa23c655d0e69a902487bbf3c303
|
||||
#2 transferring dockerfile: 37B 0.0s done
|
||||
#2 DONE 0.1s
|
||||
|
||||
...
|
||||
|
||||
pushing image (zzxwill/kubevela-appfile-demo:v1)...
|
||||
The push refers to repository [docker.io/zzxwill/kubevela-appfile-demo]
|
||||
1893e9ad9204: Preparing
|
||||
b60a6f0fd043: Preparing
|
||||
...
|
||||
89ae5c4ee501: Layer already exists
|
||||
b60a6f0fd043: Layer already exists
|
||||
1893e9ad9204: Pushed
|
||||
v1: digest: sha256:11e48ce2205a1d92c1c920b3a3f41d3ee357fa2794261dc0d0e8010068e68da6 size: 1365
|
||||
|
||||
|
||||
Rendering configs for service (express-server)...
|
||||
Writing deploy config to (.vela/deploy.yaml)
|
||||
|
||||
Applying deploy configs ...
|
||||
Checking if app has been deployed...
|
||||
App has not been deployed, creating a new deployment...
|
||||
✅ App has been deployed 🚀🚀🚀
|
||||
Port forward: vela port-forward testapp
|
||||
SSH: vela exec testapp
|
||||
Logging: vela logs testapp
|
||||
App status: vela status testapp
|
||||
Service status: vela status testapp --svc express-server
|
||||
```
|
||||
|
||||
- Check the replicas and wait for the scaling to take effect
|
||||
|
||||
Check the replicas of the application, there is one replica.
|
||||
|
||||
```
|
||||
$ vela status testapp
|
||||
About:
|
||||
|
||||
Name: testapp
|
||||
Namespace: default
|
||||
Created at: 2020-11-05 17:09:02.426632 +0800 CST
|
||||
Updated at: 2020-11-05 17:09:02.426632 +0800 CST
|
||||
|
||||
Services:
|
||||
|
||||
- Name: express-server
|
||||
Type: webservice
|
||||
HEALTHY Ready: 1/1
|
||||
Traits:
|
||||
- ✅ autoscale: type: cron minReplicas: 1 maxReplicas: 4 replicas: 1
|
||||
Last Deployment:
|
||||
Created at: 2020-11-05 17:09:03 +0800 CST
|
||||
Updated at: 2020-11-05T17:09:02+08:00
|
||||
```
|
||||
|
||||
Wait till the time clocks `startAt`, and check again. The replicas become to two, which is specified as
|
||||
`replicas` in `vela.yaml`.
|
||||
|
||||
```
|
||||
$ vela status testapp
|
||||
About:
|
||||
|
||||
Name: testapp
|
||||
Namespace: default
|
||||
Created at: 2020-11-05 17:09:02.426632 +0800 CST
|
||||
Updated at: 2020-11-05 17:09:02.426632 +0800 CST
|
||||
|
||||
Services:
|
||||
|
||||
- Name: express-server
|
||||
Type: webservice
|
||||
HEALTHY Ready: 1/1
|
||||
Traits:
|
||||
- ✅ autoscale: type: cron minReplicas: 1 maxReplicas: 4 replicas: 2
|
||||
Last Deployment:
|
||||
Created at: 2020-11-05 17:09:03 +0800 CST
|
||||
Updated at: 2020-11-05T17:09:02+08:00
|
||||
```
|
||||
|
||||
Wait after the period ends, the replicas will be one eventually.
|
||||
|
||||
|
||||
@@ -307,6 +307,10 @@ var (
|
||||
q: "specify port for container ",
|
||||
a: "8080",
|
||||
},
|
||||
{
|
||||
q: "CPU core requests for the workload ",
|
||||
a: "",
|
||||
},
|
||||
}
|
||||
for _, qa := range data {
|
||||
_, err := c.ExpectString(qa.q)
|
||||
|
||||
@@ -36,6 +36,16 @@ services:
|
||||
# scheme: "http"
|
||||
# enabled: true
|
||||
|
||||
# autoscale:
|
||||
# minReplicas: 1
|
||||
# maxReplicas: 4
|
||||
# cron:
|
||||
# startAt: "14:00"
|
||||
# duration: "2h"
|
||||
# days: "Monday, Thursday"
|
||||
# replicas: "2"
|
||||
# timezone: "America/Seattle"
|
||||
|
||||
# pi:
|
||||
# image: perl
|
||||
# cmd: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
|
||||
|
||||
@@ -2,29 +2,52 @@ output: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Autoscaler"
|
||||
spec: {
|
||||
minReplicas: parameter.minReplicas
|
||||
maxReplicas: parameter.maxReplicas
|
||||
triggers: [{
|
||||
name: parameter.name
|
||||
type: parameter.type
|
||||
condition: {
|
||||
startAt: parameter.startAt
|
||||
duration: parameter.duration
|
||||
days: parameter.days
|
||||
replicas: parameter.replicas
|
||||
timezone: parameter.timezone
|
||||
}
|
||||
}, ...]
|
||||
minReplicas: parameter.min
|
||||
maxReplicas: parameter.max
|
||||
if parameter["cpu"] != _|_ && parameter["cron"] != _|_ {
|
||||
triggers: [cpuScaler, cronScaler]
|
||||
}
|
||||
if parameter["cpu"] != _|_ && parameter["cron"] == _|_ {
|
||||
triggers: [cpuScaler]
|
||||
}
|
||||
if parameter["cpu"] == _|_ && parameter["cron"] != _|_ {
|
||||
triggers: [cronScaler]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cpuScaler: {
|
||||
type: "cpu"
|
||||
condition: {
|
||||
type: "Utilization"
|
||||
if parameter["cpu"] != _|_ {
|
||||
value: parameter.cpu
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cronScaler: {
|
||||
type: "cron"
|
||||
if parameter["cron"] != _|_ {
|
||||
condition: parameter.cron
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
minReplicas: *1 | int
|
||||
maxReplicas: *4 | int
|
||||
name: *"" | string
|
||||
type: *"cron" | string
|
||||
startAt: string
|
||||
duration: string
|
||||
days: string
|
||||
replicas: *"2" | string
|
||||
timezone: *"Asia/Shanghai" | string
|
||||
// +usage=minimal replicas of the workload
|
||||
min: int
|
||||
// +usage=maximal replicas of the workload
|
||||
max: int
|
||||
// +usage=specify the value for CPU utilization, like 80, which means 80%
|
||||
cpu?: string
|
||||
// +usage=just for `appfile`, not available for Cli usage
|
||||
cron?: {
|
||||
startAt: string
|
||||
duration: string
|
||||
// +usage=several workdays or weekends, like "Monday, Tuesday"
|
||||
days: string
|
||||
replicas: string
|
||||
// +usage=timezone, like "America/Seattle"
|
||||
timezone: string
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,17 @@ output: {
|
||||
ports: [{
|
||||
containerPort: parameter.port
|
||||
}]
|
||||
|
||||
if parameter["cpuRequests"] != _|_ {
|
||||
resources: {
|
||||
limits:
|
||||
cpu: parameter.cpuRequests
|
||||
requests:
|
||||
cpu: parameter.cpuRequests
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,4 +71,7 @@ parameter: {
|
||||
}
|
||||
}
|
||||
}]
|
||||
// +usage=CPU core requests for the workload
|
||||
// +alias=cpu-requests
|
||||
cpuRequests?: string
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ metadata:
|
||||
annotations:
|
||||
definition.oam.dev/apiVersion: standard.oam.dev/v1alpha1
|
||||
definition.oam.dev/kind: Autoscaler
|
||||
definition.oam.dev/description: "Automatically scale workloads by cron or resource utilization"
|
||||
definition.oam.dev/description: "Automatically scale workloads"
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- webservice
|
||||
@@ -16,4 +16,4 @@ spec:
|
||||
definitionRef:
|
||||
name: autoscalers.standard.oam.dev
|
||||
extension:
|
||||
template: |
|
||||
template: |
|
||||
|
||||
@@ -6,4 +6,5 @@ import (
|
||||
|
||||
const (
|
||||
CronType v1alpha1.TriggerType = "cron"
|
||||
CPUType v1alpha1.TriggerType = "cpu"
|
||||
)
|
||||
|
||||
+12
-6
@@ -9,9 +9,8 @@ import (
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
cueJson "cuelang.org/go/pkg/encoding/json"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
"github.com/oam-dev/kubevela/api/types"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
// OutputFieldName is the name of the struct contains the CR data
|
||||
@@ -96,6 +95,7 @@ func GetParameters(templatePath string) ([]types.Parameter, error) {
|
||||
continue
|
||||
}
|
||||
var param = types.Parameter{
|
||||
|
||||
Name: fi.Name,
|
||||
Required: !fi.IsOptional,
|
||||
}
|
||||
@@ -109,7 +109,8 @@ func GetParameters(templatePath string) ([]types.Parameter, error) {
|
||||
if param.Default == nil {
|
||||
param.Default = getDefaultByKind(param.Type)
|
||||
}
|
||||
param.Short, param.Usage = RetrieveComments(val)
|
||||
param.Short, param.Usage, param.Alias = RetrieveComments(val)
|
||||
|
||||
params = append(params, param)
|
||||
}
|
||||
return params, nil
|
||||
@@ -159,10 +160,12 @@ func GetDefault(val cue.Value) interface{} {
|
||||
const (
|
||||
UsagePrefix = "+usage="
|
||||
ShortPrefix = "+short="
|
||||
// AliasPrefix is an alias of the name of a parameter element, in order to making it more friendly to Cli users
|
||||
AliasPrefix = "+alias="
|
||||
)
|
||||
|
||||
func RetrieveComments(value cue.Value) (string, string) {
|
||||
var short, usage string
|
||||
func RetrieveComments(value cue.Value) (string, string, string) {
|
||||
var short, usage, alias string
|
||||
docs := value.Doc()
|
||||
for _, doc := range docs {
|
||||
lines := strings.Split(doc.Text(), "\n")
|
||||
@@ -176,7 +179,10 @@ func RetrieveComments(value cue.Value) (string, string) {
|
||||
if strings.HasPrefix(line, UsagePrefix) {
|
||||
usage = strings.TrimPrefix(line, UsagePrefix)
|
||||
}
|
||||
if strings.HasPrefix(line, AliasPrefix) {
|
||||
alias = strings.TrimPrefix(line, AliasPrefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
return short, usage
|
||||
return short, usage, alias
|
||||
}
|
||||
|
||||
@@ -5,18 +5,16 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/networking/v1beta1"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/oam-dev/kubevela/api/v1alpha1"
|
||||
|
||||
"github.com/crossplane/oam-kubernetes-runtime/pkg/oam"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
|
||||
"github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
"github.com/crossplane/oam-kubernetes-runtime/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/api/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/pkg/application"
|
||||
autoscalers "github.com/oam-dev/kubevela/pkg/controller/v1alpha1/autoscaler"
|
||||
v12 "k8s.io/api/autoscaling/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/api/networking/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
@@ -33,7 +31,12 @@ func GetChecker(traitType string, c client.Client) Checker {
|
||||
return &RouteChecker{c: c}
|
||||
case "metric":
|
||||
return &MetricChecker{c: c}
|
||||
case "autoscale":
|
||||
return &AutoscalerChecker{c: c}
|
||||
case "cronscale":
|
||||
return &AutoscalerChecker{c: c}
|
||||
}
|
||||
|
||||
return &DefaultChecker{c: c}
|
||||
}
|
||||
|
||||
@@ -132,6 +135,43 @@ func (d *RouteChecker) Check(ctx context.Context, reference runtimev1alpha1.Type
|
||||
return StatusDone, message, nil
|
||||
}
|
||||
|
||||
type AutoscalerChecker struct {
|
||||
c client.Client
|
||||
}
|
||||
|
||||
func (d *AutoscalerChecker) Check(ctx context.Context, ref runtimev1alpha1.TypedReference, _ string, appConfig *v1alpha2.ApplicationConfiguration, _ *application.Application) (CheckStatus, string, error) {
|
||||
traitName := ref.Name
|
||||
var scaler v1alpha1.Autoscaler
|
||||
if err := d.c.Get(ctx, client.ObjectKey{Namespace: appConfig.Namespace, Name: traitName}, &scaler); err != nil {
|
||||
return StatusChecking, "", err
|
||||
}
|
||||
var scalerType string
|
||||
triggers := scaler.Spec.Triggers
|
||||
if len(triggers) >= 1 {
|
||||
scalerType = string(triggers[0].Type)
|
||||
}
|
||||
|
||||
hpaName := "keda-hpa-" + traitName
|
||||
var hpa v12.HorizontalPodAutoscaler
|
||||
if err := d.c.Get(ctx, client.ObjectKey{Namespace: appConfig.Namespace, Name: hpaName}, &hpa); err != nil {
|
||||
return StatusChecking, "", err
|
||||
}
|
||||
message := fmt.Sprintf("type: %s\tminReplicas: %v\tmaxReplicas: %v\t", scalerType, *hpa.Spec.MinReplicas,
|
||||
hpa.Spec.MaxReplicas)
|
||||
if scalerType == string(autoscalers.CPUType) {
|
||||
// When attaching trait, and before the scaler trait works, `CurrentCPUUtilizationPercentage` is nil
|
||||
currentCPUUtilizationPercentage := hpa.Status.CurrentCPUUtilizationPercentage
|
||||
var zeroPercentage int32 = 0
|
||||
if currentCPUUtilizationPercentage == nil {
|
||||
currentCPUUtilizationPercentage = &zeroPercentage
|
||||
}
|
||||
message += fmt.Sprintf("CPUUtilization(target/current): %v%%/%v%%\t", *hpa.Spec.TargetCPUUtilizationPercentage,
|
||||
*currentCPUUtilizationPercentage)
|
||||
}
|
||||
message += fmt.Sprintf("replicas: %v", hpa.Status.CurrentReplicas)
|
||||
return StatusDone, message, nil
|
||||
}
|
||||
|
||||
func GetUnstructured(ctx context.Context, c client.Client, ns string, resourceRef runtimev1alpha1.TypedReference) (*unstructured.Unstructured, error) {
|
||||
resource := unstructured.Unstructured{}
|
||||
resource.SetGroupVersionKind(resourceRef.GroupVersionKind())
|
||||
|
||||
+14
-10
@@ -6,13 +6,12 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"github.com/oam-dev/kubevela/api/types"
|
||||
"github.com/oam-dev/kubevela/pkg/application"
|
||||
"github.com/oam-dev/kubevela/pkg/commands/util"
|
||||
cmdutil "github.com/oam-dev/kubevela/pkg/commands/util"
|
||||
"github.com/oam-dev/kubevela/pkg/plugins"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"github.com/spf13/pflag"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
@@ -62,30 +61,35 @@ func BaseComplete(envName string, workloadName string, appName string, flagSet *
|
||||
}
|
||||
|
||||
for _, v := range template.Parameters {
|
||||
name := v.Name
|
||||
if v.Alias != "" {
|
||||
name = v.Alias
|
||||
}
|
||||
// Cli can check required flag before make a request to backend, but API itself could not, so validate flags here
|
||||
flag := flagSet.Lookup(v.Name)
|
||||
if v.Name == "name" {
|
||||
flag := flagSet.Lookup(name)
|
||||
if name == "name" {
|
||||
continue
|
||||
}
|
||||
if flag == nil || flag.Value.String() == "" {
|
||||
if v.Required {
|
||||
return nil, fmt.Errorf("required flag(s) \"%s\" not set", v.Name)
|
||||
return nil, fmt.Errorf("required flag(s) \"%s\" not set", name)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch v.Type {
|
||||
case cue.IntKind:
|
||||
workloadData[v.Name], err = flagSet.GetInt64(v.Name)
|
||||
workloadData[v.Name], err = flagSet.GetInt64(name)
|
||||
case cue.StringKind:
|
||||
workloadData[v.Name], err = flagSet.GetString(v.Name)
|
||||
workloadData[v.Name], err = flagSet.GetString(name)
|
||||
case cue.BoolKind:
|
||||
workloadData[v.Name], err = flagSet.GetBool(v.Name)
|
||||
workloadData[v.Name], err = flagSet.GetBool(name)
|
||||
case cue.NumberKind, cue.FloatKind:
|
||||
workloadData[v.Name], err = flagSet.GetFloat64(v.Name)
|
||||
workloadData[v.Name], err = flagSet.GetFloat64(name)
|
||||
}
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "of flag of type string") {
|
||||
data, _ := flagSet.GetString(v.Name)
|
||||
data, _ := flagSet.GetString(name)
|
||||
switch v.Type {
|
||||
case cue.IntKind:
|
||||
workloadData[v.Name], err = strconv.ParseInt(data, 10, 64)
|
||||
|
||||
Reference in New Issue
Block a user