From b2678783b63b4dccda8e6b02ca1adf292e1bb183 Mon Sep 17 00:00:00 2001 From: Erwin van Eyk Date: Tue, 21 Nov 2017 08:58:33 +0100 Subject: [PATCH] fission/builder image, log collection improvement in builder (#397) Create a container image with the buidler, so we can avoid copying the builder binary into the env container during the env container build. Gather both stdout and stderr of a build into the logs. * Add Dockerfile for builder + update release scripts * Improve logging of buildermgr and builder * Add support for environment-scoped buildcmd * Fix fork/exec wd when package is a file * Update tests to also include builder image * Add logging to builder's fork/exec --- .travis.yml | 7 ++++ builder/builder.go | 45 ++++++++++++++++++++------ builder/cmd/Dockerfile | 9 ++++++ buildermgr/common.go | 12 +++++-- environments/python/builder/Dockerfile | 4 +-- hack/release.sh | 22 ++++++++++++- test/build_and_test.sh | 7 ++-- test/test_utils.sh | 24 +++++++++++--- types.go | 5 ++- 9 files changed, 113 insertions(+), 22 deletions(-) create mode 100644 builder/cmd/Dockerfile diff --git a/.travis.yml b/.travis.yml index 44aa697f..68d66368 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,13 @@ cache: - $HOME/google-cloud-sdk/ - $HOME/k8scli +services: + - docker + +before_install: + - sudo apt-get update + - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce + install: - go get github.com/Masterminds/glide - hack/travis-kube-setup.sh diff --git a/builder/builder.go b/builder/builder.go index 7981a68f..1e697069 100644 --- a/builder/builder.go +++ b/builder/builder.go @@ -31,6 +31,8 @@ import ( "time" "github.com/dchest/uniuri" + "io" + "path" ) const ( @@ -129,43 +131,68 @@ func (builder *Builder) Handler(w http.ResponseWriter, r *http.Request) { func (builder *Builder) build(command string, srcPkgPath string, deployPkgPath string) (string, error) { cmd := exec.Command(command) - cmd.Dir = srcPkgPath + + fi, err := os.Stat(srcPkgPath) + if err != nil { + return "", errors.New(fmt.Sprintf("could not find srcPkgPath: '%s'", srcPkgPath)) + } + if fi.IsDir() { + cmd.Dir = srcPkgPath + } else { + cmd.Dir = path.Dir(srcPkgPath) + } + // set env variables for build command cmd.Env = append(os.Environ(), fmt.Sprintf("%v=%v", envSrcPkg, srcPkgPath), fmt.Sprintf("%v=%v", envDeployPkg, deployPkgPath), ) - cmdReader, err := cmd.StdoutPipe() + stdout, err := cmd.StdoutPipe() if err != nil { return "", errors.New(fmt.Sprintf("Error creating stdout pipe for cmd: %v", err.Error())) } - scanner := bufio.NewScanner(cmdReader) + stderr, err := cmd.StderrPipe() + if err != nil { + return "", errors.New(fmt.Sprintf("Error creating stderr pipe for cmd: %v", err.Error())) + } + + var buildLogs string + + fmt.Println("\n=== Build Logs ===") + // Init logs + fmt.Printf("command=%v\n", command) + fmt.Printf("env=%v\n", cmd.Env) + + out := io.MultiReader(stdout, stderr) + scanner := bufio.NewScanner(out) err = cmd.Start() if err != nil { return "", errors.New(fmt.Sprintf("Error starting cmd: %v", err.Error())) } - var buildLogs string - - fmt.Println("\n=== Build Logs ===") + // Runtime logs for scanner.Scan() { output := scanner.Text() fmt.Println(output) buildLogs += fmt.Sprintf("%v\n", output) } - fmt.Println("==================\n") if err := scanner.Err(); err != nil { - return "", errors.New(fmt.Sprintf("Error reading cmd output: %v", err.Error())) + scanErr := errors.New(fmt.Sprintf("Error reading cmd output: %v", err.Error())) + fmt.Println(scanErr) + return "", scanErr } err = cmd.Wait() if err != nil { - return "", errors.New(fmt.Sprintf("Error waiting for cmd: %v", err.Error())) + cmdErr := errors.New(fmt.Sprintf("Error waiting for cmd '%v': %v", command, err.Error())) + fmt.Println(cmdErr) + return "", cmdErr } + fmt.Println("==================\n") return buildLogs, nil } diff --git a/builder/cmd/Dockerfile b/builder/cmd/Dockerfile new file mode 100644 index 00000000..31aae41a --- /dev/null +++ b/builder/cmd/Dockerfile @@ -0,0 +1,9 @@ +FROM alpine:3.5 + +RUN apk update +# Install some utility libraries for builders extending image +RUN apk add coreutils binutils findutils grep + +ADD builder /builder + +EXPOSE 8001 \ No newline at end of file diff --git a/buildermgr/common.go b/buildermgr/common.go index 0c4c2030..604c0c73 100644 --- a/buildermgr/common.go +++ b/buildermgr/common.go @@ -46,8 +46,9 @@ import ( func buildPackage(fissionClient *crd.FissionClient, kubernetesClient *kubernetes.Clientset, builderNamespace string, storageSvcUrl string, buildReq BuildRequest) (buildLogs string, err error) { - pkg, err := fissionClient.Packages( - buildReq.Package.Namespace).Get(buildReq.Package.Name) + pkg, err := fissionClient. + Packages(buildReq.Package.Namespace). + Get(buildReq.Package.Name) if err != nil { e := fmt.Sprintf("Error getting function CRD info: %v", err) log.Println(e) @@ -107,9 +108,14 @@ func buildPackage(fissionClient *crd.FissionClient, kubernetesClient *kubernetes return e, fission.MakeError(500, e) } + buildCmd := pkg.Spec.BuildCommand + if len(buildCmd) == 0 { + buildCmd = env.Spec.Builder.Command + } + pkgBuildReq := &builder.PackageBuildRequest{ SrcPkgFilename: srcPkgFilename, - BuildCommand: pkg.Spec.BuildCommand, + BuildCommand: buildCmd, } log.Printf("Start building with source package: %v", srcPkgFilename) diff --git a/environments/python/builder/Dockerfile b/environments/python/builder/Dockerfile index 4aa32245..41d18221 100644 --- a/environments/python/builder/Dockerfile +++ b/environments/python/builder/Dockerfile @@ -1,4 +1,5 @@ -FROM alpine:3.5 +ARG BUILDER_IMAGE=fission/builder:latest +FROM ${BUILDER_IMAGE} RUN apk update RUN apk add --no-cache python3 python3-dev build-base @@ -6,6 +7,5 @@ RUN pip3 install --upgrade pip RUN rm -r /root/.cache ADD defaultBuildCmd /usr/local/bin/build -ADD builder /builder EXPOSE 8001 diff --git a/hack/release.sh b/hack/release.sh index e23bdf68..9986bdc0 100755 --- a/hack/release.sh +++ b/hack/release.sh @@ -93,6 +93,24 @@ push_fetcher_image() { docker push $tag } +build_builder_image() { + version=$1 + tag=fission/builder:$version + + pushd $DIR/builder/cmd + + ./build.sh + docker build -t $tag . + + popd +} + +push_builder_image() { + version=$1 + tag=fission/builder:$version + docker push $tag +} + build_and_push_env_image() { version=$1 envdir=$2 @@ -172,13 +190,15 @@ build_all() { build_fission_bundle_image $version build_fetcher_image $version + build_builder_image $version build_all_cli build_charts $version } push_all() { push_fission_bundle_image $version - push_fetcher_image $version + push_fetcher_image $version + push_builder_image $version } tag_and_release() { diff --git a/test/build_and_test.sh b/test/build_and_test.sh index bef72533..1f4549dc 100755 --- a/test/build_and_test.sh +++ b/test/build_and_test.sh @@ -14,19 +14,22 @@ REPO=gcr.io/fission-ci IMAGE=$REPO/fission-bundle FETCHER_IMAGE=$REPO/fetcher FLUENTD_IMAGE=gcr.io/fission-ci/fluentd +BUILDER_IMAGE=$REPO/builder TAG=test +dump_system_info + build_and_push_fission_bundle $IMAGE:$TAG build_and_push_fetcher $FETCHER_IMAGE:$TAG -build_builder +build_and_push_builder $BUILDER_IMAGE:$TAG ENV='python' build_and_push_env_runtime $ENV $REPO/$ENV-env:$TAG -build_and_push_env_builder $ENV $REPO/$ENV-env-builder:$TAG +build_and_push_env_builder $ENV $REPO/$ENV-env-builder:$TAG $BUILDER_IMAGE:$TAG build_and_push_fluentd $FLUENTD_IMAGE:$TAG diff --git a/test/test_utils.sh b/test/test_utils.sh index 61eff68e..ec0a86c2 100755 --- a/test/test_utils.sh +++ b/test/test_utils.sh @@ -50,9 +50,17 @@ build_and_push_fetcher() { popd } -build_builder() { + +build_and_push_builder() { + image_tag=$1 + pushd $ROOT/builder/cmd ./build.sh + docker build -t $image_tag . + + gcloud_login + + gcloud docker -- push $image_tag popd } @@ -85,12 +93,11 @@ build_and_push_env_runtime() { build_and_push_env_builder() { env=$1 image_tag=$2 + builder_image=$3 pushd $ROOT/environments/$env/builder - builderDir=${GOPATH}/src/github.com/fission/fission/builder/cmd - cp ${builderDir}/builder . - docker build -t $image_tag . + docker build -t $image_tag --build-arg BUILDER_IMAGE=${builder_image} . gcloud_login @@ -252,6 +259,15 @@ dump_all_fission_resources() { echo "--- End objects in the fission namespace $ns ---" } +dump_system_info() { + echo "--- System Info ---" + go version + docker version + kubectl version + helm version + echo "--- End System Info ---" +} + dump_logs() { id=$1 diff --git a/types.go b/types.go index aafbfc2d..de2286f3 100644 --- a/types.go +++ b/types.go @@ -151,7 +151,10 @@ type ( FunctionEndpointPort int32 `json:"functionendpointport"` } Builder struct { - Image string `json:"image"` + // Image for containing the language runtime. + Image string `json:"image"` + + // (Optional) Default build command to run for this build environment. Command string `json:"command"` } EnvironmentSpec struct {