Add Container object to environment build and runtime specs (#413)
Environment Specs so far had only an image URL to specify a container image. This was fine for public images but fell short in a few of cases: (a) Using private image registries (b) Specifying environment variables (this is needed for workflows helm install) (c) Setting a SecurityContext for the container This change adds the Container object to both build and runtime Environments. Compatibility is preserved -- the existing ImageURL field is still used. See the comments in types.go for the overriding rules in the case that both Container and ImageURL are specified.
This commit is contained in:
committed by
Soam Vasani
parent
c76b6bacc0
commit
70a93a7302
+2
-2
@@ -22,7 +22,7 @@ minikube, you'll need to set the proper environment variables with
|
|||||||
|
|
||||||
```
|
```
|
||||||
# Get dependencies
|
# Get dependencies
|
||||||
$ glide install
|
$ glide install -v
|
||||||
|
|
||||||
# Build fission server and an image
|
# Build fission server and an image
|
||||||
$ pushd fission-bundle
|
$ pushd fission-bundle
|
||||||
@@ -41,7 +41,7 @@ minikube and its built-in docker daemon:
|
|||||||
Next, install fission with this image on your kubernetes cluster using the helm chart:
|
Next, install fission with this image on your kubernetes cluster using the helm chart:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ helm install --set "image=minikube/fission-bundle,pullPolicy=IfNotPresent,analytics=false" charts/fission-all
|
$ helm install --set "image=minikube/fission-bundle,imageTag=latest,pullPolicy=IfNotPresent,analytics=false" charts/fission-all
|
||||||
```
|
```
|
||||||
|
|
||||||
And if you're changing the CLI too, you can build it with:
|
And if you're changing the CLI too, you can build it with:
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
.DEFAULT_GOAL := build
|
.DEFAULT_GOAL := build
|
||||||
|
|
||||||
IMAGE ?= fission/fission-bundle
|
IMAGE ?= fission/fission-bundle
|
||||||
VERSION ?= 0.3.0
|
VERSION ?= latest
|
||||||
ARCH ?= amd64
|
ARCH ?= amd64
|
||||||
OS ?= linux
|
OS ?= linux
|
||||||
|
|
||||||
@@ -42,5 +42,5 @@ image-push: image
|
|||||||
docker push "$(IMAGE):$(VERSION)"
|
docker push "$(IMAGE):$(VERSION)"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf fission-bundle/fission-bundle
|
@rm -f fission-bundle/fission-bundle
|
||||||
@rm -rf fission/fission
|
@rm -f fission/fission
|
||||||
|
|||||||
@@ -497,7 +497,7 @@ func (envw *environmentWatcher) createBuilderDeployment(env *crd.Environment) (*
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Containers: []apiv1.Container{
|
Containers: []apiv1.Container{
|
||||||
{
|
fission.MergeContainerSpecs(&apiv1.Container{
|
||||||
Name: "builder",
|
Name: "builder",
|
||||||
Image: env.Spec.Builder.Image,
|
Image: env.Spec.Builder.Image,
|
||||||
ImagePullPolicy: apiv1.PullAlways,
|
ImagePullPolicy: apiv1.PullAlways,
|
||||||
@@ -530,7 +530,7 @@ func (envw *environmentWatcher) createBuilderDeployment(env *crd.Environment) (*
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}, env.Spec.Builder.Container),
|
||||||
{
|
{
|
||||||
Name: "fetcher",
|
Name: "fetcher",
|
||||||
Image: envw.fetcherImage,
|
Image: envw.fetcherImage,
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/gorilla/handlers"
|
"github.com/gorilla/handlers"
|
||||||
|
"github.com/imdario/mergo"
|
||||||
|
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func UrlForFunction(name string) string {
|
func UrlForFunction(name string) string {
|
||||||
@@ -66,3 +68,22 @@ func LoggingMiddleware(next http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MergeContainerSpecs merges container specs using a predefined order.
|
||||||
|
//
|
||||||
|
// The order of the arguments indicates which spec has precedence (lower index takes precedence over higher indexes).
|
||||||
|
// Slices and maps are merged; other fields are set only if they are a zero value.
|
||||||
|
func MergeContainerSpecs(specs ...*apiv1.Container) apiv1.Container {
|
||||||
|
result := &apiv1.Container{}
|
||||||
|
for _, spec := range specs {
|
||||||
|
if spec == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mergo.Merge(result, spec)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *result
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -214,11 +215,7 @@ func TestEnvironmentApi(t *testing.T) {
|
|||||||
|
|
||||||
e, err := g.client.EnvironmentGet(m)
|
e, err := g.client.EnvironmentGet(m)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
assert(testEnv.Spec.AllowedFunctionsPerContainer == e.Spec.AllowedFunctionsPerContainer, "env AllowedFunctionsPerContainer should match after reading")
|
assert(reflect.DeepEqual(testEnv.Spec, e.Spec), "env should match after reading")
|
||||||
assert(testEnv.Spec.Poolsize == e.Spec.Poolsize, "env Poolsize should match after reading")
|
|
||||||
assert(testEnv.Spec.Builder == e.Spec.Builder, "env Builder should match after reading")
|
|
||||||
assert(testEnv.Spec.Runtime == e.Spec.Runtime, "env Runtime should match after reading")
|
|
||||||
assert(testEnv.Spec.Version == e.Spec.Version, "env Version should match after reading")
|
|
||||||
|
|
||||||
testEnv.Metadata.ResourceVersion = m.ResourceVersion
|
testEnv.Metadata.ResourceVersion = m.ResourceVersion
|
||||||
testEnv.Spec.Runtime.Image = "another-img"
|
testEnv.Spec.Runtime.Image = "another-img"
|
||||||
@@ -266,9 +263,9 @@ func TestWatchApi(t *testing.T) {
|
|||||||
|
|
||||||
w, err := g.client.WatchGet(m)
|
w, err := g.client.WatchGet(m)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
assert((testWatch.Spec.Namespace == w.Spec.Namespace &&
|
assert(testWatch.Spec.Namespace == w.Spec.Namespace &&
|
||||||
testWatch.Spec.Type == w.Spec.Type &&
|
testWatch.Spec.Type == w.Spec.Type &&
|
||||||
testWatch.Spec.FunctionReference == w.Spec.FunctionReference), "watch should match after reading")
|
testWatch.Spec.FunctionReference == w.Spec.FunctionReference, "watch should match after reading")
|
||||||
|
|
||||||
testWatch.Metadata.Name = "yyy"
|
testWatch.Metadata.Name = "yyy"
|
||||||
m2, err := g.client.WatchCreate(testWatch)
|
m2, err := g.client.WatchCreate(testWatch)
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ func (deploy *NewDeploy) getDeploymentSpec(fn *crd.Function, env *crd.Environmen
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Containers: []apiv1.Container{
|
Containers: []apiv1.Container{
|
||||||
{
|
fission.MergeContainerSpecs(&apiv1.Container{
|
||||||
Name: fn.Metadata.Name,
|
Name: fn.Metadata.Name,
|
||||||
Image: env.Spec.Runtime.Image,
|
Image: env.Spec.Runtime.Image,
|
||||||
ImagePullPolicy: apiv1.PullIfNotPresent,
|
ImagePullPolicy: apiv1.PullIfNotPresent,
|
||||||
@@ -223,7 +223,7 @@ func (deploy *NewDeploy) getDeploymentSpec(fn *crd.Function, env *crd.Environmen
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Resources: resources,
|
Resources: resources,
|
||||||
},
|
}, env.Spec.Runtime.Container),
|
||||||
{
|
{
|
||||||
Name: "fetcher",
|
Name: "fetcher",
|
||||||
Image: deploy.fetcherImg,
|
Image: deploy.fetcherImg,
|
||||||
|
|||||||
@@ -524,7 +524,7 @@ func (gp *GenericPool) createPool() error {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Containers: []apiv1.Container{
|
Containers: []apiv1.Container{
|
||||||
{
|
fission.MergeContainerSpecs(&apiv1.Container{
|
||||||
Name: gp.env.Metadata.Name,
|
Name: gp.env.Metadata.Name,
|
||||||
Image: gp.env.Spec.Runtime.Image,
|
Image: gp.env.Spec.Runtime.Image,
|
||||||
ImagePullPolicy: gp.runtimeImagePullPolicy,
|
ImagePullPolicy: gp.runtimeImagePullPolicy,
|
||||||
@@ -560,7 +560,7 @@ func (gp *GenericPool) createPool() error {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}, gp.env.Spec.Runtime.Container),
|
||||||
{
|
{
|
||||||
Name: "fetcher",
|
Name: "fetcher",
|
||||||
Image: gp.fetcherImage,
|
Image: gp.fetcherImage,
|
||||||
|
|||||||
Generated
+9
-9
@@ -1,5 +1,5 @@
|
|||||||
hash: 03ac7555eb1f5745e82abe42a07828ffcaac3785a77e7f37a596f30db8189e7f
|
hash: 3b15246c5a7ca26271ef45e705c92351c786cfbf8ca1c093026b458e527ceefa
|
||||||
updated: 2018-02-08T22:40:25.586979477-08:00
|
updated: 2018-02-10T19:04:05.240303+01:00
|
||||||
imports:
|
imports:
|
||||||
- name: cloud.google.com/go
|
- name: cloud.google.com/go
|
||||||
version: 3b1ae45394a234c385be014e9a488f2bb6eef821
|
version: 3b1ae45394a234c385be014e9a488f2bb6eef821
|
||||||
@@ -18,7 +18,7 @@ imports:
|
|||||||
- autorest/azure
|
- autorest/azure
|
||||||
- autorest/date
|
- autorest/date
|
||||||
- name: github.com/coreos/etcd
|
- name: github.com/coreos/etcd
|
||||||
version: 6a265731e10a5137b991c1aa3a83ecefdd149d50
|
version: 9c6d93056575da4da94382f473b0ecfcd9c1443b
|
||||||
subpackages:
|
subpackages:
|
||||||
- client
|
- client
|
||||||
- name: github.com/davecgh/go-spew
|
- name: github.com/davecgh/go-spew
|
||||||
@@ -55,7 +55,7 @@ imports:
|
|||||||
- name: github.com/emicklei/go-restful-swagger12
|
- name: github.com/emicklei/go-restful-swagger12
|
||||||
version: dcef7f55730566d41eae5db10e7d6981829720f6
|
version: dcef7f55730566d41eae5db10e7d6981829720f6
|
||||||
- name: github.com/fsnotify/fsnotify
|
- name: github.com/fsnotify/fsnotify
|
||||||
version: 4da3e2cfbabc9f751898f250b49f2439785783a1
|
version: c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9
|
||||||
- name: github.com/ghodss/yaml
|
- name: github.com/ghodss/yaml
|
||||||
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
|
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
|
||||||
- name: github.com/go-openapi/analysis
|
- name: github.com/go-openapi/analysis
|
||||||
@@ -104,7 +104,7 @@ imports:
|
|||||||
- name: github.com/howeyc/gopass
|
- name: github.com/howeyc/gopass
|
||||||
version: bf9dde6d0d2c004a008c27aaee91170c786f6db8
|
version: bf9dde6d0d2c004a008c27aaee91170c786f6db8
|
||||||
- name: github.com/imdario/mergo
|
- name: github.com/imdario/mergo
|
||||||
version: 6633656539c1639d9d78127b7d47c622b5d7b6dc
|
version: 163f41321a19dd09362d4c63cc2489db2015f1f4
|
||||||
- name: github.com/influxdata/influxdb
|
- name: github.com/influxdata/influxdb
|
||||||
version: b7bb7e8359642b6e071735b50ae41f5eb343fd42
|
version: b7bb7e8359642b6e071735b50ae41f5eb343fd42
|
||||||
subpackages:
|
subpackages:
|
||||||
@@ -133,7 +133,7 @@ imports:
|
|||||||
subpackages:
|
subpackages:
|
||||||
- pb
|
- pb
|
||||||
- name: github.com/nats-io/nats-streaming-server
|
- name: github.com/nats-io/nats-streaming-server
|
||||||
version: 6fdcdfbb2589e68692a68fd5b64b1b7e7c54bf05
|
version: 33414c6f2179201f7fda8743ba89d07184e3fa77
|
||||||
subpackages:
|
subpackages:
|
||||||
- spb
|
- spb
|
||||||
- util
|
- util
|
||||||
@@ -148,7 +148,7 @@ imports:
|
|||||||
subpackages:
|
subpackages:
|
||||||
- xxHash32
|
- xxHash32
|
||||||
- name: github.com/pkg/errors
|
- name: github.com/pkg/errors
|
||||||
version: f15c970de5b76fac0b59abb32d62c17cc7bed265
|
version: 30136e27e2ac8d167177e8a583aa4c3fea5be833
|
||||||
- name: github.com/PuerkitoBio/purell
|
- name: github.com/PuerkitoBio/purell
|
||||||
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
|
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
|
||||||
- name: github.com/PuerkitoBio/urlesc
|
- name: github.com/PuerkitoBio/urlesc
|
||||||
@@ -237,7 +237,7 @@ imports:
|
|||||||
- name: k8s.io/api
|
- name: k8s.io/api
|
||||||
version: 4b8fc5be9b77d91bbb6525d18591c43699a2b4e5
|
version: 4b8fc5be9b77d91bbb6525d18591c43699a2b4e5
|
||||||
- name: k8s.io/apiextensions-apiserver
|
- name: k8s.io/apiextensions-apiserver
|
||||||
version: 0965a40c0530e110459750a7fcb9cfa4910fb944
|
version: fcd622fe88a4a6efcb5aea9e94ee87324ac1b036
|
||||||
subpackages:
|
subpackages:
|
||||||
- pkg/apis/apiextensions
|
- pkg/apis/apiextensions
|
||||||
- pkg/apis/apiextensions/v1beta1
|
- pkg/apis/apiextensions/v1beta1
|
||||||
@@ -245,7 +245,7 @@ imports:
|
|||||||
- pkg/client/clientset/clientset/scheme
|
- pkg/client/clientset/clientset/scheme
|
||||||
- pkg/client/clientset/clientset/typed/apiextensions/v1beta1
|
- pkg/client/clientset/clientset/typed/apiextensions/v1beta1
|
||||||
- name: k8s.io/apimachinery
|
- name: k8s.io/apimachinery
|
||||||
version: 80184f5f100c67bfcda6b8a848e0243fe4bc2772
|
version: 8ab5f3d8a330c2e9baaf84e39042db8d49034ae2
|
||||||
subpackages:
|
subpackages:
|
||||||
- pkg/api/equality
|
- pkg/api/equality
|
||||||
- pkg/api/errors
|
- pkg/api/errors
|
||||||
|
|||||||
@@ -58,3 +58,5 @@ import:
|
|||||||
version: ~1.2.1
|
version: ~1.2.1
|
||||||
- package: github.com/davecgh/go-spew
|
- package: github.com/davecgh/go-spew
|
||||||
version: ~1.1.0
|
version: ~1.1.0
|
||||||
|
- package: github.com/imdario/mergo
|
||||||
|
version: ~0.3.2
|
||||||
|
|||||||
+120
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Fission Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
package fission
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMergeContainerSpecs(t *testing.T) {
|
||||||
|
expected := apiv1.Container{
|
||||||
|
Name: "containerName",
|
||||||
|
Image: "testImage",
|
||||||
|
Command: []string{
|
||||||
|
"command",
|
||||||
|
},
|
||||||
|
Args: []string{
|
||||||
|
"arg1",
|
||||||
|
"arg2",
|
||||||
|
},
|
||||||
|
ImagePullPolicy: apiv1.PullNever,
|
||||||
|
TTY: true,
|
||||||
|
Env: []apiv1.EnvVar{
|
||||||
|
{
|
||||||
|
Name: "a",
|
||||||
|
Value: "b",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "c",
|
||||||
|
Value: "d",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
specs := []*apiv1.Container{
|
||||||
|
{
|
||||||
|
Name: "containerName",
|
||||||
|
Image: "testImage",
|
||||||
|
Command: []string{
|
||||||
|
"command",
|
||||||
|
},
|
||||||
|
Args: []string{
|
||||||
|
"arg1",
|
||||||
|
"arg2",
|
||||||
|
},
|
||||||
|
ImagePullPolicy: apiv1.PullNever,
|
||||||
|
TTY: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "shouldNotBeThere",
|
||||||
|
Image: "shouldNotBeThere",
|
||||||
|
Env: []apiv1.EnvVar{
|
||||||
|
{
|
||||||
|
Name: "a",
|
||||||
|
Value: "b",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ImagePullPolicy: apiv1.PullAlways,
|
||||||
|
TTY: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Env: []apiv1.EnvVar{
|
||||||
|
{
|
||||||
|
Name: "c",
|
||||||
|
Value: "d",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ImagePullPolicy: apiv1.PullIfNotPresent,
|
||||||
|
TTY: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
result := MergeContainerSpecs(specs...)
|
||||||
|
assert.Equal(t, expected, result)
|
||||||
|
|
||||||
|
// Check if merging order actually matters
|
||||||
|
var rspecs []*apiv1.Container
|
||||||
|
for i := len(specs) - 1; i >= 0; i -= 1 {
|
||||||
|
rspecs = append(rspecs, specs[i])
|
||||||
|
}
|
||||||
|
reverseResult := MergeContainerSpecs(rspecs...)
|
||||||
|
assert.NotEqual(t, expected, reverseResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeContainerSpecsSingle(t *testing.T) {
|
||||||
|
expected := apiv1.Container{
|
||||||
|
Name: "containerName",
|
||||||
|
Image: "testImage",
|
||||||
|
Command: []string{
|
||||||
|
"command",
|
||||||
|
},
|
||||||
|
Args: []string{
|
||||||
|
"arg1",
|
||||||
|
"arg2",
|
||||||
|
},
|
||||||
|
ImagePullPolicy: apiv1.PullNever,
|
||||||
|
TTY: true,
|
||||||
|
}
|
||||||
|
result := MergeContainerSpecs(&expected)
|
||||||
|
assert.EqualValues(t, expected, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeContainerSpecsNil(t *testing.T) {
|
||||||
|
expected := apiv1.Container{}
|
||||||
|
result := MergeContainerSpecs()
|
||||||
|
assert.EqualValues(t, expected, result)
|
||||||
|
}
|
||||||
Executable
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
. $(dirname $0)/test_utils.sh
|
||||||
|
|
||||||
|
FILE=$(pwd)/$1
|
||||||
|
|
||||||
|
FAILURES=0
|
||||||
|
run_test ${FILE}
|
||||||
|
exit $FAILURES
|
||||||
+19
-13
@@ -389,28 +389,34 @@ run_all_tests() {
|
|||||||
|
|
||||||
for file in $test_files
|
for file in $test_files
|
||||||
do
|
do
|
||||||
testname=${file#$ROOT/test/tests}
|
run_test ${file}
|
||||||
testpath=$file
|
done
|
||||||
|
}
|
||||||
|
|
||||||
if grep "^#test:disabled" $file
|
run_test() {
|
||||||
|
file=$1
|
||||||
|
|
||||||
|
test_name=${file#${ROOT}/test/tests}
|
||||||
|
test_path=${file}
|
||||||
|
|
||||||
|
if grep "^#test:disabled" ${file}
|
||||||
then
|
then
|
||||||
report_test_skipped $testname
|
report_test_skipped ${test_name}
|
||||||
echo ------- Skipped $testname -------
|
echo ------- Skipped ${test_name} -------
|
||||||
else
|
else
|
||||||
echo ------- Running $testname -------
|
echo ------- Running ${test_name} -------
|
||||||
pushd $(dirname $testpath)
|
pushd $(dirname ${test_path})
|
||||||
if $testpath
|
if ${test_path}
|
||||||
then
|
then
|
||||||
echo SUCCESS: $testname
|
echo [SUCCESS]: ${test_name}
|
||||||
report_test_passed $testname
|
report_test_passed ${test_name}
|
||||||
else
|
else
|
||||||
echo FAILED: $testname
|
echo [FAILED]: ${test_name}
|
||||||
export FAILURES=$(($FAILURES+1))
|
export FAILURES=$(($FAILURES+1))
|
||||||
report_test_failed $testname
|
report_test_failed ${test_name}
|
||||||
fi
|
fi
|
||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
install_and_test() {
|
install_and_test() {
|
||||||
|
|||||||
Executable
+141
@@ -0,0 +1,141 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# test_env_vars.sh - tests whether a user is able to add environment variables to a Fission environment deployment
|
||||||
|
|
||||||
|
TEST_ID=$(date +%s)
|
||||||
|
ENV=python-${TEST_ID}
|
||||||
|
FN=foo-${TEST_ID}
|
||||||
|
RESOURCE_NS=default # Change to test-specific namespace once we support namespaced CRDs
|
||||||
|
FUNCTION_NS=${FUNCTION_NAMESPACE:-fission-function}
|
||||||
|
BUILDER_NS=fission-builder
|
||||||
|
|
||||||
|
# fs
|
||||||
|
TEST_DIR=/tmp/${TEST_ID}
|
||||||
|
ENV_SPEC_FILE=${TEST_DIR}/${ENV}.yaml
|
||||||
|
FN_FILE=${TEST_DIR}/${FN}.yaml
|
||||||
|
|
||||||
|
log_exec() {
|
||||||
|
cmd=$@
|
||||||
|
echo "> ${cmd}"
|
||||||
|
${cmd}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
log "Cleaning up..."
|
||||||
|
kubectl -n ${RESOURCE_NS} delete environment/${ENV} || true
|
||||||
|
rm -rf ${TEST_DIR}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
if [ -z "${TEST_NOCLEANUP:-}" ]; then
|
||||||
|
trap cleanup EXIT
|
||||||
|
else
|
||||||
|
log "TEST_NOCLEANUP is set; not cleaning up test artifacts afterwards."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! stat ${TEST_DIR} >/dev/null 2>&1 ; then
|
||||||
|
mkdir ${TEST_DIR}
|
||||||
|
fi
|
||||||
|
|
||||||
|
getPodName() {
|
||||||
|
NS=$1
|
||||||
|
POD=$2
|
||||||
|
kubectl -n ${NS} get po -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
|
||||||
|
| grep ${POD} \
|
||||||
|
| head -n 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# retry function adapted from:
|
||||||
|
# https://unix.stackexchange.com/questions/82598/how-do-i-write-a-retry-logic-in-script-to-keep-retrying-to-run-it-upto-5-times/82610
|
||||||
|
function retry {
|
||||||
|
local n=1
|
||||||
|
local max=5
|
||||||
|
local delay=5
|
||||||
|
while true; do
|
||||||
|
"$@" && break || {
|
||||||
|
if [[ ${n} -lt ${max} ]]; then
|
||||||
|
((n++))
|
||||||
|
echo "Command '$@' failed. Attempt $n/$max:"
|
||||||
|
sleep ${delay};
|
||||||
|
else
|
||||||
|
>&2 echo "The command has failed after $n attempts."
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deploy environment (using kubectl because the Fission cli does not support the container arguments)
|
||||||
|
echo "Writing environment config to $ENV_SPEC_FILE"
|
||||||
|
cat > $ENV_SPEC_FILE <<- EOM
|
||||||
|
apiVersion: fission.io/v1
|
||||||
|
kind: Environment
|
||||||
|
metadata:
|
||||||
|
name: ${ENV}
|
||||||
|
namespace: ${RESOURCE_NS}
|
||||||
|
spec:
|
||||||
|
builder:
|
||||||
|
command: build
|
||||||
|
image: gcr.io/fission-ci/python-env-builder:test
|
||||||
|
container:
|
||||||
|
env:
|
||||||
|
- name: TEST_BUILDER_ENV_KEY
|
||||||
|
value: "TEST_BUILDER_ENV_VAR"
|
||||||
|
|
||||||
|
runtime:
|
||||||
|
image: gcr.io/fission-ci/python-env:test
|
||||||
|
container:
|
||||||
|
env:
|
||||||
|
- name: TEST_RUNTIME_ENV_KEY
|
||||||
|
value: "TEST_RUNTIME_ENV_VAR"
|
||||||
|
version: 2
|
||||||
|
poolsize: 1
|
||||||
|
EOM
|
||||||
|
log_exec kubectl -n ${RESOURCE_NS} apply -f ${ENV_SPEC_FILE}
|
||||||
|
|
||||||
|
sleep 15
|
||||||
|
# Wait for runtime and build env to be deployed
|
||||||
|
retry getPodName ${FUNCTION_NS} ${ENV} | grep '.\+'
|
||||||
|
runtimePod=$(getPodName ${FUNCTION_NS} ${ENV})
|
||||||
|
echo "function pod: ${runtimePod}."
|
||||||
|
retry getPodName ${BUILDER_NS} ${ENV} | grep '.\+'
|
||||||
|
buildPod=$(getPodName ${BUILDER_NS} ${ENV})
|
||||||
|
echo "builder pod: ${buildPod}."
|
||||||
|
|
||||||
|
# Ensure pods are running/ready
|
||||||
|
log "Waiting for ${FUNCTION_NS} ${ENV} to be available..."
|
||||||
|
echo "> kubectl -n ${FUNCTION_NS} exec ${runtimePod} -c ${ENV} env"
|
||||||
|
retry kubectl -n ${FUNCTION_NS} exec ${runtimePod} -c ${ENV} env > /dev/null
|
||||||
|
log "Runtime pod ready."
|
||||||
|
|
||||||
|
log "Waiting for ${BUILDER_NS} ${ENV} to be available..."
|
||||||
|
echo "> kubectl -n ${BUILDER_NS} exec ${buildPod} -c builder env"
|
||||||
|
retry kubectl -n ${BUILDER_NS} exec ${buildPod} -c builder env > /dev/null
|
||||||
|
log "Builder pod ready."
|
||||||
|
|
||||||
|
# Check if the env is set in the runtime
|
||||||
|
status=0
|
||||||
|
if kubectl -n ${FUNCTION_NS} exec ${runtimePod} -c ${ENV} env | grep TEST_RUNTIME_ENV_KEY=TEST_RUNTIME_ENV_VAR ; then
|
||||||
|
log "Runtime env is correct."
|
||||||
|
else
|
||||||
|
log "Runtime does not contain expected env var: TEST_RUNTIME_ENV_KEY=TEST_RUNTIME_ENV_VAR"
|
||||||
|
echo "--- Runtime Env ---"
|
||||||
|
kubectl -n ${FUNCTION_NS} exec ${runtimePod} -c ${ENV} env || true
|
||||||
|
echo "--- End Runtime Env ---"
|
||||||
|
status=5
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the env is set in the builder
|
||||||
|
if kubectl -n ${BUILDER_NS} exec ${buildPod} -c builder env | grep TEST_BUILDER_ENV_KEY=TEST_BUILDER_ENV_VAR ; then
|
||||||
|
log "Builder env is correct."
|
||||||
|
else
|
||||||
|
log "Builder does not contain expected env var: TEST_BUILDER_ENV_KEY=TEST_BUILDER_ENV_VAR"
|
||||||
|
echo "--- Builder Env ---"
|
||||||
|
kubectl -n ${BUILDER_NS} exec ${buildPod} -c builder env || true
|
||||||
|
echo "--- End Builder Env ---"
|
||||||
|
status=5
|
||||||
|
fi
|
||||||
|
exit ${status}
|
||||||
@@ -18,7 +18,7 @@ package fission
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/pkg/api/v1"
|
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -133,7 +133,7 @@ type (
|
|||||||
ConfigMaps []ConfigMapReference `json:"configmaps"`
|
ConfigMaps []ConfigMapReference `json:"configmaps"`
|
||||||
|
|
||||||
// cpu and memory resources as per K8S standards
|
// cpu and memory resources as per K8S standards
|
||||||
Resources v1.ResourceRequirements `json:"resources"`
|
Resources apiv1.ResourceRequirements `json:"resources"`
|
||||||
|
|
||||||
// InvokeStrategy is a set of controls which affect how function executes
|
// InvokeStrategy is a set of controls which affect how function executes
|
||||||
InvokeStrategy InvokeStrategy
|
InvokeStrategy InvokeStrategy
|
||||||
@@ -208,6 +208,16 @@ type (
|
|||||||
// server listens for function requests. Optional;
|
// server listens for function requests. Optional;
|
||||||
// default 8888.
|
// default 8888.
|
||||||
FunctionEndpointPort int32 `json:"functionendpointport"`
|
FunctionEndpointPort int32 `json:"functionendpointport"`
|
||||||
|
|
||||||
|
// Container allows the modification of the deployed runtime
|
||||||
|
// container using the Kubernetes Container spec. Fission overrides
|
||||||
|
// the following fields:
|
||||||
|
// - Name
|
||||||
|
// - Image; set to the Runtime.Image
|
||||||
|
// - TerminationMessagePath
|
||||||
|
// - ImagePullPolicy
|
||||||
|
// (optional)
|
||||||
|
Container *apiv1.Container `json:"container,omitempty"`
|
||||||
}
|
}
|
||||||
Builder struct {
|
Builder struct {
|
||||||
// Image for containing the language runtime.
|
// Image for containing the language runtime.
|
||||||
@@ -215,6 +225,18 @@ type (
|
|||||||
|
|
||||||
// (Optional) Default build command to run for this build environment.
|
// (Optional) Default build command to run for this build environment.
|
||||||
Command string `json:"command,omitempty"`
|
Command string `json:"command,omitempty"`
|
||||||
|
|
||||||
|
// Container allows the modification of the deployed builder
|
||||||
|
// container using the Kubernetes Container spec. Fission overrides
|
||||||
|
// the following fields:
|
||||||
|
// - Name
|
||||||
|
// - Image; set to the Builder.Image
|
||||||
|
// - Command; set to the Builder.Command
|
||||||
|
// - TerminationMessagePath
|
||||||
|
// - ImagePullPolicy
|
||||||
|
// - ReadinessProbe
|
||||||
|
// (optional)
|
||||||
|
Container *apiv1.Container `json:"container,omitempty"`
|
||||||
}
|
}
|
||||||
EnvironmentSpec struct {
|
EnvironmentSpec struct {
|
||||||
// Environment API version
|
// Environment API version
|
||||||
@@ -237,7 +259,7 @@ type (
|
|||||||
AllowAccessToExternalNetwork bool `json:"allowAccessToExternalNetwork,omitempty"`
|
AllowAccessToExternalNetwork bool `json:"allowAccessToExternalNetwork,omitempty"`
|
||||||
|
|
||||||
// Request and limit resources for the environment
|
// Request and limit resources for the environment
|
||||||
Resources v1.ResourceRequirements `json:"resources"`
|
Resources apiv1.ResourceRequirements `json:"resources"`
|
||||||
|
|
||||||
// The initial pool size for environment
|
// The initial pool size for environment
|
||||||
Poolsize int `json:"poolsize,omitempty"`
|
Poolsize int `json:"poolsize,omitempty"`
|
||||||
|
|||||||
Reference in New Issue
Block a user