diff --git a/demos/canary-successful-scenario/cleanup.sh b/demos/canary-successful-scenario/cleanup.sh index fc3ee9a8..4cbe73b9 100755 --- a/demos/canary-successful-scenario/cleanup.sh +++ b/demos/canary-successful-scenario/cleanup.sh @@ -1,4 +1,11 @@ #!/bin/bash kubectl delete canaryconfig canary-1 -kubectl delete httptrigger route-hello \ No newline at end of file +kubectl delete httptrigger route-canary + +fission fn delete --name func-v1 +fission fn delete --name func-v2 +fission package delete --orphan + +# bug in canary config cache when you re-create a config with the same name, restart controller +kubectl -n fission get pod -l application=fission-api -o name | xargs -n1 kubectl -n fission delete diff --git a/demos/canary-successful-scenario/func-v1.js b/demos/canary-successful-scenario/func-v1.js new file mode 100644 index 00000000..84617fb8 --- /dev/null +++ b/demos/canary-successful-scenario/func-v1.js @@ -0,0 +1,7 @@ + +module.exports = async function(context) { + return { + status: 200, + body: "This is Version One!\n" + }; +} diff --git a/demos/canary-successful-scenario/func-v2.js b/demos/canary-successful-scenario/func-v2.js new file mode 100644 index 00000000..3eb52335 --- /dev/null +++ b/demos/canary-successful-scenario/func-v2.js @@ -0,0 +1,7 @@ + +module.exports = async function(context) { + return { + status: 200, + body: "This is Version Two!\n" + }; +} diff --git a/demos/canary-successful-scenario/run.sh b/demos/canary-successful-scenario/run.sh index 2bdc08f6..f8e5686f 100755 --- a/demos/canary-successful-scenario/run.sh +++ b/demos/canary-successful-scenario/run.sh @@ -10,24 +10,28 @@ desc "Kubernetes cluster" run "kubectl get nodes" desc "Fission installed" -run "kubectl --namespace default get deployment" +run "kubectl --namespace fission get deployment" clear desc "NodeJS environment pods" run "kubectl --namespace fission-function get pod -l environmentName=nodejs" -desc "Function version-1" -run "fission function get --name fn1-v4" +# set up functions +fission fn create --name func-v1 --env nodejs --code func-v1.js +desc "Function version 1" +run "fission function get --name func-v1" -desc "Function version-2" -run "fission function get --name fn1-v5" +fission fn create --name func-v2 --env nodejs --code func-v2.js +desc "Function version 2" +run "fission function get --name func-v2" desc "Create a route \(HTTP trigger\) the version-1 of the function with weight 100% and version-2 with weight 0%" -run "fission route create --name route-hello --method GET --url /hello --function fn1-v5 --weight 0 --function fn1-v4 --weight 100" +run "fission route create --name route-canary --method GET --url /canary --function func-v2 --weight 0 --function func-v1 --weight 100" -desc "Create a canary config to gradually increment the weight of version-2 by a step of 20 every 1 minute" -run "fission canary-config create --name canary-1 --funcN fn1-v5 --funcN-1 fn1-v4 --httptrigger route-hello --increment-step 30 --increment-interval 30s --failure-threshold 10" +desc "Start sending requests to the route" +run_bg "hey -n 100000 -c 1 http://$FISSION_ROUTER/canary" + +desc "Create a canary config: with an increment of 10 percent, every 1 minute, rolling back if 10% of requests fail" +run "fission canary-config create --name canary-1 --funcN func-v2 --funcN-1 func-v1 --httptrigger route-canary --increment-step 10 --increment-interval 30s --failure-threshold 10" -desc "Fire requests to the route" -run "ab -n 10000 -c 1 http://$FISSION_ROUTER/hello" diff --git a/demos/cncf-webinar/cleanup.sh b/demos/cncf-webinar/cleanup.sh new file mode 100644 index 00000000..07c292a3 --- /dev/null +++ b/demos/cncf-webinar/cleanup.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +fission fn delete --name hello +fission route delete --name $(fission route list|grep hello|cut -f1 -d' ') diff --git a/demos/cncf-webinar/func-v1.js b/demos/cncf-webinar/func-v1.js new file mode 100644 index 00000000..84617fb8 --- /dev/null +++ b/demos/cncf-webinar/func-v1.js @@ -0,0 +1,7 @@ + +module.exports = async function(context) { + return { + status: 200, + body: "This is Version One!\n" + }; +} diff --git a/demos/cncf-webinar/func-v2.js b/demos/cncf-webinar/func-v2.js new file mode 100644 index 00000000..3eb52335 --- /dev/null +++ b/demos/cncf-webinar/func-v2.js @@ -0,0 +1,7 @@ + +module.exports = async function(context) { + return { + status: 200, + body: "This is Version Two!\n" + }; +} diff --git a/demos/cncf-webinar/hello.js b/demos/cncf-webinar/hello.js new file mode 100644 index 00000000..4bcbf4f8 --- /dev/null +++ b/demos/cncf-webinar/hello.js @@ -0,0 +1,7 @@ + +module.exports = async function(context) { + return { + status: 200, + body: "Hello, world!\n" + }; +} diff --git a/demos/cncf-webinar/run.sh b/demos/cncf-webinar/run.sh new file mode 100644 index 00000000..5fc1269d --- /dev/null +++ b/demos/cncf-webinar/run.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +DEMO_RUN_FAST=1 +ROOT_DIR=$(dirname $0)/.. +. $ROOT_DIR/util.sh + + +# +# General setup intro +# +desc "Our Kubernetes cluster" +run "kubectl get nodes" + +desc "Fission is installed" +run "kubectl --namespace fission get deployment" + +clear + +# +# Hello world, environments, cold starts +# + +desc "Hello world function" +run "cat hello.js" + +desc "Add the NodeJS environment to fission" +run "fission env create --name nodejs --image fission/node-env" + +desc "NodeJS environment pods" +run "kubectl --namespace fission-function get pod -l environmentName=nodejs" + +desc "Upload our function to fission" +run "fission function create --name hello --env nodejs --code hello.js" + +desc "Set up a route (aka HTTP Trigger) for the function" +run "fission route create --method GET --url /hello --function hello" + +sleep 2 + +desc "Finally, run the function" +run "time -p curl http://$FISSION_ROUTER/hello" + +desc "Run the function again" +run "time -p curl http://$FISSION_ROUTER/hello" +run "time -p curl http://$FISSION_ROUTER/hello" + +desc "The pod is now labeled by the function name" +run "kubectl --namespace fission-function get pod -l functionName=hello" + +# +# Declarative Specs. +# +# Use go for this one to show off the fact that we can do builds. +# +clear + +pushd declarative + +desc "Declaratively specified app" +run "ls" + +desc "Declaratively specified app" +run "ls specs" + +desc "Validate configs" +run "fission spec validate" + +desc "Deploy application, wait for build to finish" +run "fission spec apply --wait" + +desc "Invoke our new function" +run "fission function test --name hello-go" + +# +# Live Reload (still in the same app) +# +clear + + + + +popd + +# +# Record replay +# +clear + +# +# Canary Deployments +# +clear + +# set up functions +fission fn create --name func-v1 --env nodejs --code func-v1.js +desc "Function version 1" +run "fission function get --name func-v1" + +fission fn create --name func-v2 --env nodejs --code func-v2.js +desc "Function version 2" +run "fission function get --name func-v2" + +desc "Create a route \(HTTP trigger\) the version-1 of the function with weight 100% and version-2 with weight 0%" +run "fission route create --name route-canary --method GET --url /canary --function func-v2 --weight 0 --function func-v1 --weight 100" + +desc "Start sending requests to the route" +run_bg "hey -n 100000 -c 1 http://$FISSION_ROUTER/canary" + +desc "Create a canary config: with an increment of 10 percent, every 1 minute, rolling back if 10% of requests fail" +run "fission canary-config create --name canary-1 --funcN func-v2 --funcN-1 func-v1 --httptrigger route-canary --increment-step 10 --increment-interval 30s --failure-threshold 10" + + + diff --git a/demos/cncf-webinar/test.sh b/demos/cncf-webinar/test.sh new file mode 100755 index 00000000..655d4c94 --- /dev/null +++ b/demos/cncf-webinar/test.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +DEMO_RUN_FAST=1 +ROOT_DIR=$(dirname $0)/.. +. $ROOT_DIR/util.sh + + +desc "one" +run "sleep 30" + +desc "two" +run "echo hi" diff --git a/demos/declarative-specs/cleanup.sh b/demos/declarative-specs/cleanup.sh new file mode 100755 index 00000000..3ddd7b19 --- /dev/null +++ b/demos/declarative-specs/cleanup.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +fission spec destroy + +# this one is generated in run.sh +rm specs/function-hello-go.yaml + +rm *.~?~ + diff --git a/demos/declarative-specs/hello.go b/demos/declarative-specs/hello.go new file mode 100644 index 00000000..03c28d29 --- /dev/null +++ b/demos/declarative-specs/hello.go @@ -0,0 +1,12 @@ +package main + +import ( + "net/http" +) + +// Handler is the entry point for this fission function + +func Handler(w http.ResponseWriter, r *http.Request) { + msg := "Hello, CNCF Webinar!\n" + w.Write([]byte(msg)) +} diff --git a/demos/declarative-specs/run.sh b/demos/declarative-specs/run.sh new file mode 100755 index 00000000..2cb06ec9 --- /dev/null +++ b/demos/declarative-specs/run.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +DEMO_RUN_FAST=1 +ROOT_DIR=$(dirname $0)/.. +. $ROOT_DIR/util.sh + +desc "Declaratively specified app" +run "ls specs" + +desc "Generate initial YAML, so we don't have to write it by hand" +run "fission function create --spec --name hello-go --env go --src hello.go --entrypoint Handler" + +desc "Generated function YAML" +run "tail -25 specs/function-hello-go.yaml" + +desc "Deploy on cluster, and wait for build result" +run "fission spec apply --wait" + +desc "Invoke the function" +run "fission function test --name hello-go" + +desc "Live-reload: auto build + deploy on save" +run "fission spec apply --watch" + diff --git a/demos/declarative-specs/specs/README b/demos/declarative-specs/specs/README new file mode 100644 index 00000000..1db3f9a5 --- /dev/null +++ b/demos/declarative-specs/specs/README @@ -0,0 +1,42 @@ + +Fission Specs +============= + +This is a set of specifications for a Fission app. This includes functions, +environments, and triggers; we collectively call these things "resources". + +How to use these specs +---------------------- + +These specs are handled with the 'fission spec' command. See 'fission spec --help'. + +'fission spec apply' will "apply" all resources specified in this directory to your +cluster. That means it checks what resources exist on your cluster, what resources are +specified in the specs directory, and reconciles the difference by creating, updating or +deleting resources on the cluster. + +'fission spec apply' will also package up your source code (or compiled binaries) and +upload the archives to the cluster if needed. It uses 'ArchiveUploadSpec' resources in +this directory to figure out which files to archive. + +You can use 'fission spec apply --watch' to watch for file changes and continuously keep +the cluster updated. + +You can add YAMLs to this directory by writing them manually, but it's easier to generate +them. Use 'fission function create --spec' to generate a function spec, +'fission environment create --spec' to generate an environment spec, and so on. + +You can edit any of the files in this directory, except 'fission-deployment-config.yaml', +which contains a UID that you should never change. To apply your changes simply use +'fission spec apply'. + +fission-deployment-config.yaml +------------------------------ + +fission-deployment-config.yaml contains a UID. This UID is what fission uses to correlate +resources on the cluster to resources in this directory. + +All resources created by 'fission spec apply' are annotated with this UID. Resources on +the cluster that are _not_ annotated with this UID are never modified or deleted by +fission. + diff --git a/demos/declarative-specs/specs/fission-deployment-config.yaml b/demos/declarative-specs/specs/fission-deployment-config.yaml new file mode 100644 index 00000000..c262bc42 --- /dev/null +++ b/demos/declarative-specs/specs/fission-deployment-config.yaml @@ -0,0 +1,7 @@ +# This file is generated by the 'fission spec init' command. +# See the README in this directory for background and usage information. +# Do not edit the UID below: that will break 'fission spec apply' +apiVersion: fission.io/v1 +kind: DeploymentConfig +name: declarative-specs +uid: e20fe7b4-b012-4ae0-98bd-0f968d21d397 diff --git a/demos/declarative-specs/specs/function-hello-go.yaml b/demos/declarative-specs/specs/function-hello-go.yaml new file mode 100644 index 00000000..081af66c --- /dev/null +++ b/demos/declarative-specs/specs/function-hello-go.yaml @@ -0,0 +1,51 @@ +include: +- hello.go +kind: ArchiveUploadSpec +name: hello-go + +--- +apiVersion: fission.io/v1 +kind: Package +metadata: + creationTimestamp: null + name: hello-go-xfxy + namespace: default +spec: + deployment: + checksum: {} + environment: + name: go + namespace: default + source: + checksum: {} + type: url + url: archive://hello-go +status: + buildstatus: pending + +--- +apiVersion: fission.io/v1 +kind: Function +metadata: + creationTimestamp: null + name: hello-go + namespace: default +spec: + InvokeStrategy: + ExecutionStrategy: + ExecutorType: poolmgr + MaxScale: 1 + MinScale: 0 + TargetCPUPercent: 80 + StrategyType: execution + configmaps: null + environment: + name: go + namespace: default + package: + functionName: Handler + packageref: + name: hello-go-xfxy + namespace: default + resources: {} + secrets: null diff --git a/demos/record-replay/cleanup.sh b/demos/record-replay/cleanup.sh new file mode 100755 index 00000000..27b80272 --- /dev/null +++ b/demos/record-replay/cleanup.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +fission fn delete --name hi-py +fission route delete --name $(fission route list|grep hi|cut -f1 -d' ') +fission recorder delete --name my-recorder +kubectl -n fission delete pod redis-0 diff --git a/demos/record-replay/hi.py b/demos/record-replay/hi.py new file mode 100644 index 00000000..f440600f --- /dev/null +++ b/demos/record-replay/hi.py @@ -0,0 +1,7 @@ +from flask import request +from flask import current_app + + +def main(): + name=request.args["name"] + return "Hello, %s" % name diff --git a/demos/record-replay/run.sh b/demos/record-replay/run.sh new file mode 100755 index 00000000..1242a99f --- /dev/null +++ b/demos/record-replay/run.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +DEMO_RUN_FAST=1 +ROOT_DIR=$(dirname $0)/.. +. $ROOT_DIR/util.sh + +desc "A simple function that takes inputs" +run "cat hi.py" + +desc "Set up function" +run "fission function create --name hi-py --env python --code hi.py --entrypoint hi.main" + +desc "Set up route" +run "fission route create --function hi-py --url /hi --method GET" + +desc "Set up recorder" +run "fission recorder create --name my-recorder --function hi-py" + +desc "Run function" +run "curl http://$FISSION_ROUTER/hi?name=world" + +desc "View recording" +run "fission records view -v" + +requid=$(fission records view -v|tail -1|cut -f1 -d' ') + +desc "Replay recording" +run "fission replay --reqUID $requid" diff --git a/demos/util.sh b/demos/util.sh index 4c37f39c..79128227 100644 --- a/demos/util.sh +++ b/demos/util.sh @@ -54,5 +54,23 @@ function run() { echo -e "\b " } +function run_bg() { + maybe_first_prompt + rate=25 + if [ -n "$DEMO_RUN_FAST" ]; then + rate=1000 + fi + echo "$green$1$reset" | pv -qL $rate + if [ -n "$DEMO_RUN_FAST" ]; then + sleep 0.5 + fi + $1 & + echo + echo -n ">" + read -s + echo -e "\b " +} + + SSH_NODE=$(kubectl get nodes | tail -1 | cut -f1 -d' ') diff --git a/fission/spec.go b/fission/spec.go index 2d43c9a6..82c3e34e 100644 --- a/fission/spec.go +++ b/fission/spec.go @@ -396,7 +396,7 @@ func (fr *FissionResources) validate() error { for _, f := range fr.functions { if _, ok := environments[fmt.Sprintf("%s:%s", f.Spec.Environment.Name, f.Spec.Environment.Namespace)]; !ok { - log.Warn(fmt.Sprintf("Environment %s is referred in function %s but not declared in specs", f.Spec.Environment.Name, f.Metadata.Name)) + log.Warn(fmt.Sprintf("Environment %s is referenced in function %s but not declared in specs", f.Spec.Environment.Name, f.Metadata.Name)) } }