Skip to content

Commit

Permalink
implement cli vela system live-diff
Browse files Browse the repository at this point in the history
move dry-run and live-diff into an independent pkg

WIP add sample and doc

WIP unit test for live-diff

add unit test

Signed-off-by: roy wang <seiwy2010@gmail.com>
  • Loading branch information
captainroy-hy committed Apr 12, 2021
1 parent 26163aa commit f075b33
Show file tree
Hide file tree
Showing 33 changed files with 2,828 additions and 142 deletions.
482 changes: 482 additions & 0 deletions docs/en/platform-engineers/debug-test-cue.md

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions docs/examples/live-diff/app-modified.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: livediff-demo
spec:
components:
- name: myweb-1
type: myworker
properties:
image: "busybox"
cmd:
- sleep
- "2000" # change a component property
lives: "3"
enemies: "alien"
traits:
- type: myingress
properties:
domain: "www.example.com"
http:
"/": 90 # change a trait
# - type: myscaler # remove a trait
# properties:
# replicas: 2
- name: myweb-2
type: myworker
properties: # no change on component property
image: "busybox"
cmd:
- sleep
- "1000"
lives: "3"
enemies: "alien"
traits:
- type: myingress # add a trait
properties:
domain: "www.example.com"
http:
"/": 90
- name: myweb-3 # add a component
type: myworker
properties:
image: "busybox"
cmd:
- sleep
- "1000"
lives: "3"
enemies: "alien"
traits:
- type: myingress
properties:
domain: "www.example.com"
http:
"/": 90
33 changes: 33 additions & 0 deletions docs/examples/live-diff/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: livediff-demo
spec:
components:
- name: myweb-1
type: myworker
properties:
image: "busybox"
cmd:
- sleep
- "1000"
lives: "3"
enemies: "alien"
traits:
- type: myingress
properties:
domain: "www.example.com"
http:
"/": 80
- type: myscaler
properties:
replicas: 2
- name: myweb-2
type: myworker
properties:
image: "busybox"
cmd:
- sleep
- "1000"
lives: "3"
enemies: "alien"
62 changes: 62 additions & 0 deletions docs/examples/live-diff/definitions/myingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
apiVersion: core.oam.dev/v1beta1
kind: TraitDefinition
metadata:
name: myingress
spec:
appliesToWorkloads:
- "*"
schematic:
cue:
template: |
import (
kubev1 "kube/v1"
network "kube/networking.k8s.io/v1beta1"
)
parameter: {
domain: string
http: [string]: int
}
outputs: {
service: kubev1.#Service
ingress: network.#Ingress
}
// trait template can have multiple outputs in one trait
outputs: service: {
metadata:
name: context.name
spec: {
selector:
"app.oam.dev/component": context.name
ports: [
for k, v in parameter.http {
port: v
targetPort: v
},
]
}
}
outputs: ingress: {
metadata:
name: context.name
spec: {
rules: [{
host: parameter.domain
http: {
paths: [
for k, v in parameter.http {
path: k
backend: {
serviceName: context.name
servicePort: v
}
},
]
}
}]
}
}
28 changes: 28 additions & 0 deletions docs/examples/live-diff/definitions/myscaler.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
apiVersion: core.oam.dev/v1beta1
kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/description: "Configures replicas for your service."
name: myscaler
spec:
appliesToWorkloads:
- webservice
- worker
definitionRef:
name: manualscalertraits.core.oam.dev
workloadRefPath: spec.workloadRef
schematic:
cue:
template: |
outputs: scaler: {
apiVersion: "core.oam.dev/v1alpha2"
kind: "ManualScalerTrait"
spec: {
replicaCount: parameter.replicas
}
}
parameter: {
//+short=r
//+usage=Replicas of the workload
replicas: *1 | int
}
49 changes: 49 additions & 0 deletions docs/examples/live-diff/definitions/myworker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
name: myworker
spec:
workload:
definition:
apiVersion: apps/v1
kind: Deployment
schematic:
cue:
template: |
import (
apps "kube/apps/v1"
)
output: apps.#Deployment
output: {
spec: {
selector: matchLabels: {
"app.oam.dev/component": context.name
}
template: {
metadata: labels: {
"app.oam.dev/component": context.name
}
spec: {
containers: [{
name: context.name
image: parameter.image
if parameter["cmd"] != _|_ {
command: parameter.cmd
}
}]
}
}
}
}
parameter: {
// +usage=Which image would you like to use for your service
// +short=i
image: string
// +usage=Commands to run in the container
cmd?: [...string]
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/AlecAivazis/survey/v2 v2.1.1
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869
github.com/briandowns/spinner v1.11.1
github.com/coreos/prometheus-operator v0.41.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a h1:pv34s756C4pEXnjgPfGYgdhg/ZdajGhyOvzx8k+23nw=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b h1:uUXgbcPDK3KpW29o4iy7GtuappbWT0l5NaMo9H9pJDw=
github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0=
Expand Down
53 changes: 44 additions & 9 deletions pkg/appfile/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@ import (
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/appfile/config"
velacue "github.com/oam-dev/kubevela/pkg/cue"
"github.com/oam-dev/kubevela/pkg/dsl/definition"
"github.com/oam-dev/kubevela/pkg/dsl/process"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
"github.com/oam-dev/kubevela/pkg/oam/util"
)
Expand All @@ -42,19 +45,39 @@ const (
AppfileBuiltinConfig = "config"
)

// TemplateLoaderFn load template of a capability definition
type TemplateLoaderFn func(context.Context, discoverymapper.DiscoveryMapper, client.Reader, string, types.CapType) (*Template, error)

// LoadTemplate load template of a capability definition
func (fn TemplateLoaderFn) LoadTemplate(ctx context.Context, dm discoverymapper.DiscoveryMapper, c client.Reader, capName string, capType types.CapType) (*Template, error) {
return fn(ctx, dm, c, capName, capType)
}

// Parser is an application parser
type Parser struct {
client client.Client
dm discoverymapper.DiscoveryMapper
pd *definition.PackageDiscover
client client.Client
dm discoverymapper.DiscoveryMapper
pd *definition.PackageDiscover
tmplLoader TemplateLoaderFn
}

// NewApplicationParser create appfile parser
func NewApplicationParser(cli client.Client, dm discoverymapper.DiscoveryMapper, pd *definition.PackageDiscover) *Parser {
return &Parser{
client: cli,
dm: dm,
pd: pd,
client: cli,
dm: dm,
pd: pd,
tmplLoader: LoadTemplate,
}
}

// NewDryRunApplicationParser create an appfile parser for DryRun
func NewDryRunApplicationParser(cli client.Client, dm discoverymapper.DiscoveryMapper, pd *definition.PackageDiscover, defs []oam.Object) *Parser {
return &Parser{
client: cli,
dm: dm,
pd: pd,
tmplLoader: DryRunTemplateLoader(defs),
}
}

Expand All @@ -81,7 +104,7 @@ func (p *Parser) GenerateAppFile(ctx context.Context, app *v1beta1.Application)
// parseWorkload resolve an ApplicationComponent and generate a Workload
// containing ALL information required by an Appfile.
func (p *Parser) parseWorkload(ctx context.Context, comp v1beta1.ApplicationComponent, appName, ns string) (*Workload, error) {
templ, err := LoadTemplate(ctx, p.dm, p.client, comp.Type, types.TypeComponentDefinition)
templ, err := p.tmplLoader.LoadTemplate(ctx, p.dm, p.client, comp.Type, types.TypeComponentDefinition)
if err != nil && !kerrors.IsNotFound(err) {
return nil, errors.WithMessagef(err, "fetch type of %s", comp.Name)
}
Expand Down Expand Up @@ -132,7 +155,7 @@ func (p *Parser) parseWorkload(ctx context.Context, comp v1beta1.ApplicationComp
workload.Traits = append(workload.Traits, trait)
}
for scopeType, instanceName := range comp.Scopes {
gvk, err := GetScopeGVK(ctx, p.client, p.dm, scopeType)
gvk, err := getScopeGVK(ctx, p.client, p.dm, scopeType)
if err != nil {
return nil, err
}
Expand All @@ -145,7 +168,7 @@ func (p *Parser) parseWorkload(ctx context.Context, comp v1beta1.ApplicationComp
}

func (p *Parser) parseTrait(ctx context.Context, name string, properties map[string]interface{}) (*Trait, error) {
templ, err := LoadTemplate(ctx, p.dm, p.client, name, types.TypeTrait)
templ, err := p.tmplLoader.LoadTemplate(ctx, p.dm, p.client, name, types.TypeTrait)
if kerrors.IsNotFound(err) {
return nil, errors.Errorf("trait definition of %s not found", name)
}
Expand Down Expand Up @@ -250,3 +273,15 @@ func getComponentSetting(settingParamName string, params map[string]interface{})
}
return nil, fmt.Errorf("failed to get the value of component setting %s", settingParamName)
}

func getScopeGVK(ctx context.Context, cli client.Reader, dm discoverymapper.DiscoveryMapper,
name string) (schema.GroupVersionKind, error) {
var gvk schema.GroupVersionKind
sd := new(v1alpha2.ScopeDefinition)
err := util.GetDefinition(ctx, cli, sd, name)
if err != nil {
return gvk, err
}

return util.GetGVKFromDefinition(dm, sd.Spec.Reference)
}

0 comments on commit f075b33

Please sign in to comment.