diff --git a/commands/ansible-operator-base/main.go b/commands/ansible-operator-base/main.go new file mode 100644 index 00000000000..f55e204ff4a --- /dev/null +++ b/commands/ansible-operator-base/main.go @@ -0,0 +1,46 @@ +// Copyright 2018 The Operator-SDK 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 main + +import ( + "log" + + "github.com/operator-framework/operator-sdk/internal/util/projutil" + "github.com/operator-framework/operator-sdk/pkg/scaffold" + "github.com/operator-framework/operator-sdk/pkg/scaffold/ansible" + "github.com/operator-framework/operator-sdk/pkg/scaffold/input" +) + +// main renders scaffolds that are required to build the ansible operator base +// image. It is intended for release engineering use only. After running this, +// you can `dep ensure` and then `operator-sdk build`. +func main() { + cfg := &input.Config{ + AbsProjectPath: projutil.MustGetwd(), + ProjectName: "ansible-operator", + } + + s := &scaffold.Scaffold{} + err := s.Execute(cfg, + &ansible.Main{}, + &ansible.GopkgToml{}, + &ansible.DockerfileHybrid{}, + &ansible.Entrypoint{}, + &ansible.UserSetup{}, + ) + if err != nil { + log.Fatalf("add scaffold failed: (%v)", err) + } +} diff --git a/commands/operator-sdk/cmd/migrate.go b/commands/operator-sdk/cmd/migrate.go new file mode 100644 index 00000000000..3df3f3147a1 --- /dev/null +++ b/commands/operator-sdk/cmd/migrate.go @@ -0,0 +1,92 @@ +// Copyright 2018 The Operator-SDK 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 cmd + +import ( + "log" + "os" + "path/filepath" + + "github.com/operator-framework/operator-sdk/internal/util/projutil" + "github.com/operator-framework/operator-sdk/pkg/scaffold" + "github.com/operator-framework/operator-sdk/pkg/scaffold/ansible" + "github.com/operator-framework/operator-sdk/pkg/scaffold/input" + + "github.com/spf13/cobra" +) + +func NewMigrateCmd() *cobra.Command { + return &cobra.Command{ + Use: "migrate", + Short: "Adds source code for an operator", + Long: `operator-sdk migrate adds a main.go source file and any associated source files for an operator that is not of the "go" type.`, + Run: migrateRun, + } +} + +func migrateRun(cmd *cobra.Command, args []string) { + projutil.MustInProjectRoot() + + _ = projutil.CheckAndGetProjectGoPkg() + + opType := projutil.GetOperatorType() + switch opType { + case projutil.OperatorTypeAnsible: + migrateAnsible() + default: + log.Fatalf("operator of type %s cannot be migrated.", opType) + } +} + +func migrateAnsible() { + wd, err := os.Getwd() + if err != nil { + log.Fatalf("could not identify current working directory: (%v)", err) + } + + cfg := &input.Config{ + AbsProjectPath: projutil.MustGetwd(), + ProjectName: filepath.Base(wd), + } + + dockerfile := ansible.DockerfileHybrid{ + Watches: true, + Roles: true, + } + _, err = os.Stat("playbook.yaml") + if err == nil { + dockerfile.Playbook = true + } else if !os.IsNotExist(err) { + log.Fatalf("error trying to stat playbook.yaml: (%v)", err) + } + + dockerfilePath := filepath.Join(scaffold.BuildDir, scaffold.DockerfileFile) + err = os.Rename(dockerfilePath, dockerfilePath+".sdkold") + if err != nil { + log.Fatalf("failed to rename Dockerfile: (%v)", err) + } + + s := &scaffold.Scaffold{} + err = s.Execute(cfg, + &ansible.Main{}, + &ansible.GopkgToml{}, + &dockerfile, + &ansible.Entrypoint{}, + &ansible.UserSetup{}, + ) + if err != nil { + log.Fatalf("add scaffold failed: (%v)", err) + } +} diff --git a/commands/operator-sdk/cmd/root.go b/commands/operator-sdk/cmd/root.go index fe33772c3d9..195cedc3f2f 100644 --- a/commands/operator-sdk/cmd/root.go +++ b/commands/operator-sdk/cmd/root.go @@ -35,6 +35,7 @@ func NewRootCmd() *cobra.Command { cmd.AddCommand(NewCompletionCmd()) cmd.AddCommand(NewTestCmd()) cmd.AddCommand(NewPrintDepsCmd()) + cmd.AddCommand(NewMigrateCmd()) return cmd } diff --git a/doc/dev/testing/travis-build.md b/doc/dev/testing/travis-build.md index 259ebe90e10..8a658f92e21 100644 --- a/doc/dev/testing/travis-build.md +++ b/doc/dev/testing/travis-build.md @@ -69,13 +69,14 @@ The Go, Ansible, and Helm tests then differ in what tests they run. ### Ansible tests 1. Run [ansible e2e tests][ansible-e2e]. - 1. Build base ansible operator image from [`test/ansible-operator`][ansible-base]. - 2. Create and configure a new ansible type memcached-operator. - 3. Create cluster resources. - 4. Wait for operator to be ready. - 5. Create a memcached CR and wait for it to be ready. - 6. Create a configmap that the memcached-operator is configured to delete using a finalizer. - 7. Delete memcached CR and verify that the finalizer deleted the configmap. + 1. Create base ansible operator source by running [`commands/ansible-operator-base/main.go`][ansible-base]. + 2. Build base ansible operator binary and image from source. + 3. Create and configure a new ansible type memcached-operator. + 4. Create cluster resources. + 5. Wait for operator to be ready. + 6. Create a memcached CR and wait for it to be ready. + 7. Create a configmap that the memcached-operator is configured to delete using a finalizer. + 8. Delete memcached CR and verify that the finalizer deleted the configmap. **NOTE**: All created resources, including the namespace, are deleted using a bash trap when the test finishes @@ -106,8 +107,8 @@ The markdown test does not create a new cluster and runs in a barebones travis V [go-e2e]: ../../../hack/tests/e2e-go.sh [tls-tests]: ../../../test/e2e/tls_util_test.go [ansible-e2e]: ../../../hack/tests/e2e-ansible.sh -[ansible-base]: ../../../test/ansible-operator +[ansible-base]: ../../../commands/ansible-operator-base/main.go [helm-e2e]: ../../../hack/tests/e2e-helm.sh [helm-base]: ../../../test/helm-operator [marker-github]: https://github.com/crawford/marker -[marker-local]: ../../../hack/ci/marker \ No newline at end of file +[marker-local]: ../../../hack/ci/marker diff --git a/hack/image/build-ansible-image.sh b/hack/image/build-ansible-image.sh index d75de823bb2..49f496277be 100755 --- a/hack/image/build-ansible-image.sh +++ b/hack/image/build-ansible-image.sh @@ -2,8 +2,24 @@ set -eux +source hack/lib/test_lib.sh + +ROOTDIR="$(pwd)" +GOTMP="$(mktemp -d -p $GOPATH/src)" +trap_add 'rm -rf $GOTMP' EXIT +BASEIMAGEDIR="$GOTMP/ansible-operator" +mkdir -p "$BASEIMAGEDIR" + # build operator binary and base image -go build -o test/ansible-operator/ansible-operator test/ansible-operator/cmd/ansible-operator/main.go -pushd test/ansible-operator -docker build -t "$1" . +pushd "$BASEIMAGEDIR" +go run "$ROOTDIR/commands/ansible-operator-base/main.go" +dep ensure + +# overwrite operator-sdk source with the latest source from the local checkout +pushd vendor/github.com/operator-framework/ +rm -Rf operator-sdk/* +cp -a "$ROOTDIR"/{pkg,version,LICENSE} operator-sdk/ +popd + +operator-sdk build $1 popd diff --git a/hack/tests/e2e-ansible.sh b/hack/tests/e2e-ansible.sh index 71349fb2e72..b063b7e13b3 100755 --- a/hack/tests/e2e-ansible.sh +++ b/hack/tests/e2e-ansible.sh @@ -1,30 +1,96 @@ #!/usr/bin/env bash +set -eux + source hack/lib/test_lib.sh DEST_IMAGE="quay.io/example/memcached-operator:v0.0.2" - -set -ex +ROOTDIR="$(pwd)" +GOTMP="$(mktemp -d -p $GOPATH/src)" +trap_add 'rm -rf $GOTMP' EXIT + +deploy_operator() { + kubectl create -f "$OPERATORDIR/deploy/service_account.yaml" + kubectl create -f "$OPERATORDIR/deploy/role.yaml" + kubectl create -f "$OPERATORDIR/deploy/role_binding.yaml" + kubectl create -f "$OPERATORDIR/deploy/crds/ansible_v1alpha1_memcached_crd.yaml" + kubectl create -f "$OPERATORDIR/deploy/operator.yaml" +} + +remove_operator() { + kubectl delete --ignore-not-found=true -f "$OPERATORDIR/deploy/service_account.yaml" + kubectl delete --ignore-not-found=true -f "$OPERATORDIR/deploy/role.yaml" + kubectl delete --ignore-not-found=true -f "$OPERATORDIR/deploy/role_binding.yaml" + kubectl delete --ignore-not-found=true -f "$OPERATORDIR/deploy/crds/ansible_v1alpha1_memcached_crd.yaml" + kubectl delete --ignore-not-found=true -f "$OPERATORDIR/deploy/operator.yaml" +} + +test_operator() { + # wait for operator pod to run + if ! timeout 1m kubectl rollout status deployment/memcached-operator; + then + echo FAIL: operator failed to run + kubectl logs deployment/memcached-operator + exit 1 + fi + + # create CR + kubectl create -f deploy/crds/ansible_v1alpha1_memcached_cr.yaml + if ! timeout 20s bash -c -- 'until kubectl get deployment -l app=memcached | grep memcached; do sleep 1; done'; + then + echo FAIL: operator failed to create memcached Deployment + kubectl logs deployment/memcached-operator + exit 1 + fi + memcached_deployment=$(kubectl get deployment -l app=memcached -o jsonpath="{..metadata.name}") + if ! timeout 1m kubectl rollout status deployment/${memcached_deployment}; + then + echo FAIL: memcached Deployment failed rollout + kubectl logs deployment/${memcached_deployment} + exit 1 + fi + + + # make a configmap that the finalizer should remove + kubectl create configmap deleteme + trap_add 'kubectl delete --ignore-not-found configmap deleteme' EXIT + + kubectl delete -f ${OPERATORDIR}/deploy/crds/ansible_v1alpha1_memcached_cr.yaml --wait=true + # if the finalizer did not delete the configmap... + if kubectl get configmap deleteme 2> /dev/null; + then + echo FAIL: the finalizer did not delete the configmap + kubectl logs deployment/memcached-operator + exit 1 + fi + + # The deployment should get garbage collected, so we expect to fail getting the deployment. + if ! timeout 20s bash -c -- "while kubectl get deployment ${memcached_deployment} 2> /dev/null; do sleep 1; done"; + then + echo FAIL: memcached Deployment did not get garbage collected + kubectl logs deployment/memcached-operator + exit 1 + fi + + ## TODO enable when this is fixed: https://github.com/operator-framework/operator-sdk/issues/818 + # if kubectl logs deployment/memcached-operator | grep -i error; + # then + # echo FAIL: the operator log includes errors + # kubectl logs deployment/memcached-operator + # exit 1 + # fi +} # switch to the "default" namespace if on openshift, to match the minikube test if which oc 2>/dev/null; then oc project default; fi -# Make a test directory for Ansible tests so we avoid using default GOPATH. -# Save test directory so we can delete it on exit. -ANSIBLE_TEST_DIR="$(mktemp -d)" -trap_add 'rm -rf $ANSIBLE_TEST_DIR' EXIT -cp -a test/ansible-* "$ANSIBLE_TEST_DIR" -pushd "$ANSIBLE_TEST_DIR" - -# Ansible tests should not run in a Golang environment. -unset GOPATH GOROOT - # create and build the operator +pushd "$GOTMP" operator-sdk new memcached-operator --api-version=ansible.example.com/v1alpha1 --kind=Memcached --type=ansible -cp ansible-memcached/tasks.yml memcached-operator/roles/Memcached/tasks/main.yml -cp ansible-memcached/defaults.yml memcached-operator/roles/Memcached/defaults/main.yml -cp -a ansible-memcached/memfin memcached-operator/roles/ -cat ansible-memcached/watches-finalizer.yaml >> memcached-operator/watches.yaml +cp "$ROOTDIR/test/ansible-memcached/tasks.yml" memcached-operator/roles/Memcached/tasks/main.yml +cp "$ROOTDIR/test/ansible-memcached/defaults.yml" memcached-operator/roles/Memcached/defaults/main.yml +cp -a "$ROOTDIR/test/ansible-memcached/memfin" memcached-operator/roles/ +cat "$ROOTDIR/test/ansible-memcached/watches-finalizer.yaml" >> memcached-operator/watches.yaml pushd memcached-operator sed -i 's|\(FROM quay.io/operator-framework/ansible-operator\)\(:.*\)\?|\1:dev|g' build/Dockerfile @@ -32,68 +98,37 @@ operator-sdk build "$DEST_IMAGE" sed -i "s|REPLACE_IMAGE|$DEST_IMAGE|g" deploy/operator.yaml sed -i 's|Always|Never|g' deploy/operator.yaml -DIR2="$(pwd)" -# deploy the operator -kubectl create -f deploy/service_account.yaml -trap_add 'kubectl delete -f ${DIR2}/deploy/service_account.yaml' EXIT -kubectl create -f deploy/role.yaml -trap_add 'kubectl delete -f ${DIR2}/deploy/role.yaml' EXIT -kubectl create -f deploy/role_binding.yaml -trap_add 'kubectl delete -f ${DIR2}/deploy/role_binding.yaml' EXIT -kubectl create -f deploy/crds/ansible_v1alpha1_memcached_crd.yaml -trap_add 'kubectl delete -f ${DIR2}/deploy/crds/ansible_v1alpha1_memcached_crd.yaml' EXIT -kubectl create -f deploy/operator.yaml -trap_add 'kubectl delete -f ${DIR2}/deploy/operator.yaml' EXIT - -# wait for operator pod to run -if ! timeout 1m kubectl rollout status deployment/memcached-operator; -then - kubectl logs deployment/memcached-operator - exit 1 -fi +OPERATORDIR="$(pwd)" -# create CR -kubectl create -f deploy/crds/ansible_v1alpha1_memcached_cr.yaml -if ! timeout 20s bash -c -- 'until kubectl get deployment -l app=memcached | grep memcached; do sleep 1; done'; -then - kubectl logs deployment/memcached-operator - exit 1 -fi -memcached_deployment=$(kubectl get deployment -l app=memcached -o jsonpath="{..metadata.name}") -if ! timeout 1m kubectl rollout status deployment/${memcached_deployment}; -then - kubectl logs deployment/${memcached_deployment} - exit 1 -fi +deploy_operator +trap_add 'remove_operator' EXIT +test_operator +remove_operator -# make a configmap that the finalizer should remove -kubectl create configmap deleteme -trap_add 'kubectl delete --ignore-not-found configmap deleteme' EXIT +echo "###" +echo "### Base image testing passed" +echo "### Now testing migrate to hybrid operator" +echo "###" -kubectl delete -f ${DIR2}/deploy/crds/ansible_v1alpha1_memcached_cr.yaml --wait=true -# if the finalizer did not delete the configmap... -if kubectl get configmap deleteme; -then - echo FAIL: the finalizer did not delete the configmap - kubectl logs deployment/memcached-operator - exit 1 -fi +operator-sdk migrate -# The deployment should get garbage collected, so we expect to fail getting the deployment. -if ! timeout 20s bash -c -- "while kubectl get deployment ${memcached_deployment}; do sleep 1; done"; +if [[ ! -e build/Dockerfile.sdkold ]]; then - kubectl logs deployment/memcached-operator + echo FAIL the old Dockerfile should have been renamed to Dockerfile.sdkold exit 1 fi +dep ensure +# overwrite operator-sdk source with the latest source from the local checkout +pushd vendor/github.com/operator-framework/ +rm -Rf operator-sdk/* +cp -a "$ROOTDIR"/{pkg,version,LICENSE} operator-sdk/ +popd + +operator-sdk build "$DEST_IMAGE" -## TODO enable when this is fixed: https://github.com/operator-framework/operator-sdk/issues/818 -# if kubectl logs deployment/memcached-operator | grep -i error; -# then - # echo FAIL: the operator log includes errors - # kubectl logs deployment/memcached-operator - # exit 1 -# fi +deploy_operator +test_operator popd popd diff --git a/pkg/scaffold/ansible/dockerfilehybrid.go b/pkg/scaffold/ansible/dockerfilehybrid.go new file mode 100644 index 00000000000..2fd711b4671 --- /dev/null +++ b/pkg/scaffold/ansible/dockerfilehybrid.go @@ -0,0 +1,82 @@ +// Copyright 2018 The Operator-SDK 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 ansible + +import ( + "path/filepath" + + "github.com/operator-framework/operator-sdk/pkg/scaffold" + "github.com/operator-framework/operator-sdk/pkg/scaffold/input" +) + +//DockerfileHybrid - Dockerfile for a hybrid operator +type DockerfileHybrid struct { + input.Input + + // Playbook - if true, include a COPY statement for playbook.yaml + Playbook bool + + // Roles - if true, include a COPY statement for the roles directory + Roles bool + + // Watches - if true, include a COPY statement for watches.yaml + Watches bool +} + +// GetInput - gets the input +func (d *DockerfileHybrid) GetInput() (input.Input, error) { + if d.Path == "" { + d.Path = filepath.Join(scaffold.BuildDir, scaffold.DockerfileFile) + } + d.TemplateBody = dockerFileHybridAnsibleTmpl + return d.Input, nil +} + +const dockerFileHybridAnsibleTmpl = `FROM ansible/ansible-runner + +RUN yum remove -y ansible python-idna +RUN pip uninstall ansible-runner -y + +RUN pip install --upgrade setuptools +RUN pip install ansible ansible-runner openshift kubernetes ansible-runner-http idna==2.7 + +RUN mkdir -p /etc/ansible \ + && echo "localhost ansible_connection=local" > /etc/ansible/hosts \ + && echo '[defaults]' > /etc/ansible/ansible.cfg \ + && echo 'roles_path = /opt/ansible/roles' >> /etc/ansible/ansible.cfg \ + && echo 'library = /usr/share/ansible/openshift' >> /etc/ansible/ansible.cfg + +ENV OPERATOR=/usr/local/bin/ansible-operator \ + USER_UID=1001 \ + USER_NAME=ansible-operator\ + HOME=/opt/ansible + +# install operator binary +COPY build/_output/bin/{{.ProjectName}} ${OPERATOR} + +COPY bin /usr/local/bin +RUN /usr/local/bin/user_setup + +{{- if .Roles }} +COPY roles/ ${HOME}/roles/{{ end }} +{{- if .Playbook }} +COPY playbook.yaml ${HOME}/playbook.yaml{{ end }} +{{- if .Watches }} +COPY watches.yaml ${HOME}/watches.yaml{{ end }} + +ENTRYPOINT ["/usr/local/bin/entrypoint"] + +USER ${USER_UID} +` diff --git a/pkg/scaffold/ansible/entrypoint.go b/pkg/scaffold/ansible/entrypoint.go new file mode 100644 index 00000000000..d5ebb8b1786 --- /dev/null +++ b/pkg/scaffold/ansible/entrypoint.go @@ -0,0 +1,49 @@ +// Copyright 2018 The Operator-SDK 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 ansible + +import ( + "path/filepath" + + "github.com/operator-framework/operator-sdk/pkg/scaffold/input" +) + +// Entrypoint - entrypoint script +type Entrypoint struct { + input.Input +} + +func (e *Entrypoint) GetInput() (input.Input, error) { + if e.Path == "" { + e.Path = filepath.Join("bin", "entrypoint") + } + e.TemplateBody = entrypointTmpl + e.IsExec = true + return e.Input, nil +} + +const entrypointTmpl = `#!/bin/bash -e + +# This is documented here: +# https://docs.openshift.com/container-platform/3.11/creating_images/guidelines.html#openshift-specific-guidelines + +if ! whoami &>/dev/null; then + if [ -w /etc/passwd ]; then + echo "${USER_NAME:-runner}:x:$(id -u):$(id -g):${USER_NAME:-runner} user:${HOME}:/sbin/nologin" >> /etc/passwd + fi +fi + +exec ${OPERATOR} --watches-file=/opt/ansible/watches.yaml $@ +` diff --git a/pkg/scaffold/ansible/gopkgtoml.go b/pkg/scaffold/ansible/gopkgtoml.go new file mode 100644 index 00000000000..501fa66a27c --- /dev/null +++ b/pkg/scaffold/ansible/gopkgtoml.go @@ -0,0 +1,52 @@ +// Copyright 2018 The Operator-SDK 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 ansible + +import ( + "github.com/operator-framework/operator-sdk/pkg/scaffold" + "github.com/operator-framework/operator-sdk/pkg/scaffold/input" +) + +// GopkgToml - the Gopkg.toml file for a hybrid operator +type GopkgToml struct { + input.Input +} + +func (s *GopkgToml) GetInput() (input.Input, error) { + if s.Path == "" { + s.Path = scaffold.GopkgTomlFile + } + s.TemplateBody = gopkgTomlTmpl + return s.Input, nil +} + +const gopkgTomlTmpl = `[[constraint]] + name = "github.com/operator-framework/operator-sdk" + # The version rule is used for a specific release and the master branch for in between releases. + branch = "master" + # version = "=v0.0.7" + +[[constraint]] + name = "github.com/sirupsen/logrus" + version = "1.0.5" + +[[constraint]] + name = "sigs.k8s.io/controller-runtime" + version = "=v0.1.8" + +[prune] + go-tests = true + unused-packages = true +` diff --git a/test/ansible-operator/cmd/ansible-operator/main.go b/pkg/scaffold/ansible/main.go similarity index 81% rename from test/ansible-operator/cmd/ansible-operator/main.go rename to pkg/scaffold/ansible/main.go index ed582e8e183..97099116429 100644 --- a/test/ansible-operator/cmd/ansible-operator/main.go +++ b/pkg/scaffold/ansible/main.go @@ -12,7 +12,28 @@ // See the License for the specific language governing permissions and // limitations under the License. -package main +package ansible + +import ( + "path/filepath" + + "github.com/operator-framework/operator-sdk/pkg/scaffold/input" +) + +// Main - main source file for ansible operator +type Main struct { + input.Input +} + +func (m *Main) GetInput() (input.Input, error) { + if m.Path == "" { + m.Path = filepath.Join("cmd", "manager", "main.go") + } + m.TemplateBody = mainTmpl + return m.Input, nil +} + +const mainTmpl = `package main import ( "os" @@ -72,7 +93,7 @@ func main() { ControllerMap: cMap, }) if err != nil { - log.Fatalf("error starting proxy: (%v)", err) + log.Fatalf("error starting proxy: %v", err) } // start the operator @@ -80,8 +101,10 @@ func main() { // wait for either to finish err = <-done - if err != nil { - log.Fatal(err) + if err == nil { + log.Info("Exiting") + } else { + log.Fatal(err.Error()) } - log.Info("Exiting.") } +` diff --git a/pkg/scaffold/ansible/usersetup.go b/pkg/scaffold/ansible/usersetup.go new file mode 100644 index 00000000000..9513eb7d6cc --- /dev/null +++ b/pkg/scaffold/ansible/usersetup.go @@ -0,0 +1,50 @@ +// Copyright 2018 The Operator-SDK 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 ansible + +import ( + "path/filepath" + + "github.com/operator-framework/operator-sdk/pkg/scaffold/input" +) + +// UserSetup - userSetup script +type UserSetup struct { + input.Input +} + +func (u *UserSetup) GetInput() (input.Input, error) { + if u.Path == "" { + u.Path = filepath.Join("bin", "user_setup") + } + u.TemplateBody = userSetupTmpl + u.IsExec = true + return u.Input, nil +} + +const userSetupTmpl = `#!/bin/sh +set -x + +# ensure $HOME exists and is accessible by group 0 (we don't know what the runtime UID will be) +mkdir -p ${HOME}/.ansible/tmp +chown -R ${USER_UID}:0 ${HOME} +chmod -R ug+rwx ${HOME} + +# runtime user will need to be able to self-insert in /etc/passwd +chmod g+rw /etc/passwd + +# no need for this script to remain in the image after running +rm $0 +` diff --git a/test/ansible-operator/Dockerfile b/test/ansible-operator/Dockerfile deleted file mode 100644 index 323c55797a8..00000000000 --- a/test/ansible-operator/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -FROM ansible/ansible-runner - -RUN yum remove -y ansible python-idna -RUN pip uninstall ansible-runner -y - -RUN pip install --upgrade setuptools -RUN pip install ansible ansible-runner openshift kubernetes ansible-runner-http idna==2.7 - -RUN mkdir -p /etc/ansible \ - && echo "localhost ansible_connection=local" > /etc/ansible/hosts \ - && echo '[defaults]' > /etc/ansible/ansible.cfg \ - && echo 'roles_path = /opt/ansible/roles' >> /etc/ansible/ansible.cfg \ - && echo 'library = /usr/share/ansible/openshift' >> /etc/ansible/ansible.cfg - -ENV OPERATOR=/usr/local/bin/ansible-operator \ - USER_UID=1001 \ - USER_NAME=ansible-operator \ - HOME=/opt/ansible - -# install operator binary -COPY ansible-operator ${OPERATOR} - -COPY bin /usr/local/bin -RUN /usr/local/bin/user_setup - -ENTRYPOINT ["/usr/local/bin/entrypoint"] - -USER ${USER_UID} diff --git a/test/ansible-operator/README.md b/test/ansible-operator/README.md deleted file mode 100644 index c336cd1abaa..00000000000 --- a/test/ansible-operator/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This directory temporarily holds the artifacts that are required to build the -ansible operator base image, until they find a more permanent home. diff --git a/test/ansible-operator/bin/entrypoint b/test/ansible-operator/bin/entrypoint deleted file mode 100755 index 3d8aaa9f59c..00000000000 --- a/test/ansible-operator/bin/entrypoint +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -e - -# This is documented here: -# https://docs.openshift.com/container-platform/3.10/creating_images/guidelines.html#openshift-specific-guidelines - -if ! whoami &>/dev/null; then - if [ -w /etc/passwd ]; then - echo "${USER_NAME:-runner}:x:$(id -u):$(id -g):${USER_NAME:-runner} user:${HOME}:/sbin/nologin" >> /etc/passwd - fi -fi - -#Watches file will be overridden if the flag is provided again. -exec ${OPERATOR} --watches-file=/opt/ansible/watches.yaml $@ diff --git a/test/ansible-operator/bin/user_setup b/test/ansible-operator/bin/user_setup deleted file mode 100755 index 1e36064cbf0..00000000000 --- a/test/ansible-operator/bin/user_setup +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -set -x - -# ensure $HOME exists and is accessible by group 0 (we don't know what the runtime UID will be) -mkdir -p ${HOME} -chown ${USER_UID}:0 ${HOME} -chmod ug+rwx ${HOME} - -# runtime user will need to be able to self-insert in /etc/passwd -chmod g+rw /etc/passwd - -# no need for this script to remain in the image after running -rm $0