Skip to content

Commit fe8fc7f

Browse files
committed
adds migrate command and ansible base image scaffolds
The `operator-sdk migrate` command adds go source and other files necessary to convert an ansible operator to a hybrid operator. The scaffolds used for `migrate` are also made available for use in creating the ansible-operator base image through `commands/ansible-operator-base/main.go`.
1 parent a199c14 commit fe8fc7f

File tree

13 files changed

+517
-133
lines changed

13 files changed

+517
-133
lines changed

Diff for: commands/ansible-operator-base/main.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2018 The Operator-SDK Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package main
16+
17+
import (
18+
"log"
19+
20+
"github.com/operator-framework/operator-sdk/internal/util/projutil"
21+
"github.com/operator-framework/operator-sdk/pkg/scaffold"
22+
"github.com/operator-framework/operator-sdk/pkg/scaffold/ansible"
23+
"github.com/operator-framework/operator-sdk/pkg/scaffold/input"
24+
)
25+
26+
// main renders scaffolds that are required to build the ansible operator base
27+
// image. It is intended for release engineering use only. After running this,
28+
// you can `dep ensure` and then `operator-sdk build`.
29+
func main() {
30+
cfg := &input.Config{
31+
AbsProjectPath: projutil.MustGetwd(),
32+
ProjectName: "ansible-operator",
33+
}
34+
35+
s := &scaffold.Scaffold{}
36+
err := s.Execute(cfg,
37+
&ansible.Main{},
38+
&ansible.GopkgToml{},
39+
&ansible.DockerfileHybrid{},
40+
&ansible.Entrypoint{},
41+
&ansible.UserSetup{},
42+
)
43+
if err != nil {
44+
log.Fatalf("add scaffold failed: (%v)", err)
45+
}
46+
}

Diff for: commands/operator-sdk/cmd/migrate.go

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright 2018 The Operator-SDK Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package cmd
16+
17+
import (
18+
"log"
19+
"os"
20+
"path/filepath"
21+
22+
"github.com/operator-framework/operator-sdk/internal/util/projutil"
23+
"github.com/operator-framework/operator-sdk/pkg/scaffold"
24+
"github.com/operator-framework/operator-sdk/pkg/scaffold/ansible"
25+
"github.com/operator-framework/operator-sdk/pkg/scaffold/input"
26+
27+
"github.com/spf13/cobra"
28+
)
29+
30+
func NewMigrateCmd() *cobra.Command {
31+
return &cobra.Command{
32+
Use: "migrate",
33+
Short: "Adds source code for an operator",
34+
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.`,
35+
Run: migrateRun,
36+
}
37+
}
38+
39+
func migrateRun(cmd *cobra.Command, args []string) {
40+
projutil.MustInProjectRoot()
41+
42+
_ = projutil.CheckAndGetProjectGoPkg()
43+
44+
opType := projutil.GetOperatorType()
45+
switch opType {
46+
case projutil.OperatorTypeAnsible:
47+
migrateAnsible()
48+
default:
49+
log.Fatalf("operator of type %s cannot be migrated.", opType)
50+
}
51+
}
52+
53+
func migrateAnsible() {
54+
wd, err := os.Getwd()
55+
if err != nil {
56+
log.Fatalf("could not identify current working directory: (%v)", err)
57+
}
58+
59+
cfg := &input.Config{
60+
AbsProjectPath: projutil.MustGetwd(),
61+
ProjectName: filepath.Base(wd),
62+
}
63+
64+
dockerfile := ansible.DockerfileHybrid{
65+
Watches: true,
66+
Roles: true,
67+
}
68+
_, err = os.Stat("playbook.yaml")
69+
if err == nil {
70+
dockerfile.Playbook = true
71+
} else if !os.IsNotExist(err) {
72+
log.Fatalf("error trying to stat playbook.yaml: (%v)", err)
73+
}
74+
75+
dockerfilePath := filepath.Join(scaffold.BuildDir, scaffold.DockerfileFile)
76+
err = os.Rename(dockerfilePath, dockerfilePath+".sdkold")
77+
if err != nil {
78+
log.Fatalf("failed to rename Dockerfile: (%v)", err)
79+
}
80+
81+
s := &scaffold.Scaffold{}
82+
err = s.Execute(cfg,
83+
&ansible.Main{},
84+
&ansible.GopkgToml{},
85+
&dockerfile,
86+
&ansible.Entrypoint{},
87+
&ansible.UserSetup{},
88+
)
89+
if err != nil {
90+
log.Fatalf("add scaffold failed: (%v)", err)
91+
}
92+
}

Diff for: commands/operator-sdk/cmd/root.go

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func NewRootCmd() *cobra.Command {
3535
cmd.AddCommand(NewCompletionCmd())
3636
cmd.AddCommand(NewTestCmd())
3737
cmd.AddCommand(NewPrintDepsCmd())
38+
cmd.AddCommand(NewMigrateCmd())
3839

3940
return cmd
4041
}

Diff for: hack/tests/e2e-ansible.sh

+116-71
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,149 @@
11
#!/usr/bin/env bash
22

3+
set -eux
4+
35
source hack/lib/test_lib.sh
46

57
DEST_IMAGE="quay.io/example/memcached-operator:v0.0.2"
6-
7-
set -ex
8+
ROOTDIR="$(pwd)"
9+
GOTMP="$(mktemp -d -p $GOPATH/src)"
10+
trap_add 'rm -rf $GOTMP' EXIT
11+
BASEIMAGEDIR="$GOTMP/ansible-operator"
12+
mkdir -p "$BASEIMAGEDIR"
13+
14+
deploy_operator() {
15+
kubectl create -f "$OPERATORDIR/deploy/service_account.yaml"
16+
kubectl create -f "$OPERATORDIR/deploy/role.yaml"
17+
kubectl create -f "$OPERATORDIR/deploy/role_binding.yaml"
18+
kubectl create -f "$OPERATORDIR/deploy/crds/ansible_v1alpha1_memcached_crd.yaml"
19+
kubectl create -f "$OPERATORDIR/deploy/operator.yaml"
20+
}
21+
22+
remove_operator() {
23+
kubectl delete --ignore-not-found=true -f "$OPERATORDIR/deploy/service_account.yaml"
24+
kubectl delete --ignore-not-found=true -f "$OPERATORDIR/deploy/role.yaml"
25+
kubectl delete --ignore-not-found=true -f "$OPERATORDIR/deploy/role_binding.yaml"
26+
kubectl delete --ignore-not-found=true -f "$OPERATORDIR/deploy/crds/ansible_v1alpha1_memcached_crd.yaml"
27+
kubectl delete --ignore-not-found=true -f "$OPERATORDIR/deploy/operator.yaml"
28+
}
29+
30+
test_operator() {
31+
# wait for operator pod to run
32+
if ! timeout 1m kubectl rollout status deployment/memcached-operator;
33+
then
34+
echo FAIL: operator failed to run
35+
kubectl logs deployment/memcached-operator
36+
exit 1
37+
fi
38+
39+
# create CR
40+
kubectl create -f deploy/crds/ansible_v1alpha1_memcached_cr.yaml
41+
if ! timeout 20s bash -c -- 'until kubectl get deployment -l app=memcached | grep memcached; do sleep 1; done';
42+
then
43+
echo FAIL: operator failed to create memcached Deployment
44+
kubectl logs deployment/memcached-operator
45+
exit 1
46+
fi
47+
memcached_deployment=$(kubectl get deployment -l app=memcached -o jsonpath="{..metadata.name}")
48+
if ! timeout 1m kubectl rollout status deployment/${memcached_deployment};
49+
then
50+
echo FAIL: memcached Deployment failed rollout
51+
kubectl logs deployment/${memcached_deployment}
52+
exit 1
53+
fi
54+
55+
56+
# make a configmap that the finalizer should remove
57+
kubectl create configmap deleteme
58+
trap_add 'kubectl delete --ignore-not-found configmap deleteme' EXIT
59+
60+
kubectl delete -f ${OPERATORDIR}/deploy/crds/ansible_v1alpha1_memcached_cr.yaml --wait=true
61+
# if the finalizer did not delete the configmap...
62+
if kubectl get configmap deleteme;
63+
then
64+
echo FAIL: the finalizer did not delete the configmap
65+
kubectl logs deployment/memcached-operator
66+
exit 1
67+
fi
68+
69+
# The deployment should get garbage collected, so we expect to fail getting the deployment.
70+
if ! timeout 20s bash -c -- "while kubectl get deployment ${memcached_deployment}; do sleep 1; done";
71+
then
72+
echo FAIL: memcached Deployment did not get garbage collected
73+
kubectl logs deployment/memcached-operator
74+
exit 1
75+
fi
76+
77+
## TODO enable when this is fixed: https://github.com/operator-framework/operator-sdk/issues/818
78+
# if kubectl logs deployment/memcached-operator | grep -i error;
79+
# then
80+
# echo FAIL: the operator log includes errors
81+
# kubectl logs deployment/memcached-operator
82+
# exit 1
83+
# fi
84+
}
885

986
# switch to the "default" namespace if on openshift, to match the minikube test
1087
if which oc 2>/dev/null; then oc project default; fi
1188

1289
# build operator binary and base image
13-
go build -o test/ansible-operator/ansible-operator test/ansible-operator/cmd/ansible-operator/main.go
14-
pushd test/ansible-operator
15-
docker build -t quay.io/water-hole/ansible-operator .
90+
pushd "$BASEIMAGEDIR"
91+
go run "$ROOTDIR/commands/ansible-operator-base/main.go"
92+
dep ensure
93+
94+
# overwrite operator-sdk source with the latest source from the local checkout
95+
pushd vendor/github.com/operator-framework/
96+
rm -Rf operator-sdk/*
97+
cp -a "$ROOTDIR"/{pkg,version,LICENSE} operator-sdk/
1698
popd
1799

18-
# Make a test directory for Ansible tests so we avoid using default GOPATH.
19-
# Save test directory so we can delete it on exit.
20-
ANSIBLE_TEST_DIR="$(mktemp -d)"
21-
trap_add 'rm -rf $ANSIBLE_TEST_DIR' EXIT
22-
cp -a test/ansible-* "$ANSIBLE_TEST_DIR"
23-
pushd "$ANSIBLE_TEST_DIR"
24-
25-
# Ansible tests should not run in a Golang environment.
26-
unset GOPATH GOROOT
100+
operator-sdk build quay.io/water-hole/ansible-operator
101+
popd
27102

28103
# create and build the operator
104+
pushd "$GOTMP"
29105
operator-sdk new memcached-operator --api-version=ansible.example.com/v1alpha1 --kind=Memcached --type=ansible
30-
cp ansible-memcached/tasks.yml memcached-operator/roles/Memcached/tasks/main.yml
31-
cp ansible-memcached/defaults.yml memcached-operator/roles/Memcached/defaults/main.yml
32-
cp -a ansible-memcached/memfin memcached-operator/roles/
33-
cat ansible-memcached/watches-finalizer.yaml >> memcached-operator/watches.yaml
106+
cp "$ROOTDIR/test/ansible-memcached/tasks.yml" memcached-operator/roles/Memcached/tasks/main.yml
107+
cp "$ROOTDIR/test/ansible-memcached/defaults.yml" memcached-operator/roles/Memcached/defaults/main.yml
108+
cp -a "$ROOTDIR/test/ansible-memcached/memfin" memcached-operator/roles/
109+
cat "$ROOTDIR/test/ansible-memcached/watches-finalizer.yaml" >> memcached-operator/watches.yaml
34110

35111
pushd memcached-operator
36112
operator-sdk build "$DEST_IMAGE"
37113
sed -i "s|REPLACE_IMAGE|$DEST_IMAGE|g" deploy/operator.yaml
38114
sed -i 's|Always|Never|g' deploy/operator.yaml
39115

40-
DIR2="$(pwd)"
41-
# deploy the operator
42-
kubectl create -f deploy/service_account.yaml
43-
trap_add 'kubectl delete -f ${DIR2}/deploy/service_account.yaml' EXIT
44-
kubectl create -f deploy/role.yaml
45-
trap_add 'kubectl delete -f ${DIR2}/deploy/role.yaml' EXIT
46-
kubectl create -f deploy/role_binding.yaml
47-
trap_add 'kubectl delete -f ${DIR2}/deploy/role_binding.yaml' EXIT
48-
kubectl create -f deploy/crds/ansible_v1alpha1_memcached_crd.yaml
49-
trap_add 'kubectl delete -f ${DIR2}/deploy/crds/ansible_v1alpha1_memcached_crd.yaml' EXIT
50-
kubectl create -f deploy/operator.yaml
51-
trap_add 'kubectl delete -f ${DIR2}/deploy/operator.yaml' EXIT
52-
53-
# wait for operator pod to run
54-
if ! timeout 1m kubectl rollout status deployment/memcached-operator;
55-
then
56-
kubectl logs deployment/memcached-operator
57-
exit 1
58-
fi
116+
OPERATORDIR="$(pwd)"
59117

60-
# create CR
61-
kubectl create -f deploy/crds/ansible_v1alpha1_memcached_cr.yaml
62-
if ! timeout 20s bash -c -- 'until kubectl get deployment -l app=memcached | grep memcached; do sleep 1; done';
63-
then
64-
kubectl logs deployment/memcached-operator
65-
exit 1
66-
fi
67-
memcached_deployment=$(kubectl get deployment -l app=memcached -o jsonpath="{..metadata.name}")
68-
if ! timeout 1m kubectl rollout status deployment/${memcached_deployment};
69-
then
70-
kubectl logs deployment/${memcached_deployment}
71-
exit 1
72-
fi
118+
deploy_operator
119+
trap_add 'remove_operator' EXIT
120+
test_operator
121+
remove_operator
73122

74-
# make a configmap that the finalizer should remove
75-
kubectl create configmap deleteme
76-
trap_add 'kubectl delete --ignore-not-found configmap deleteme' EXIT
123+
echo "###"
124+
echo "### Base image testing passed"
125+
echo "### Now testing migrate to hybrid operator"
126+
echo "###"
77127

78-
kubectl delete -f ${DIR2}/deploy/crds/ansible_v1alpha1_memcached_cr.yaml --wait=true
79-
# if the finalizer did not delete the configmap...
80-
if kubectl get configmap deleteme;
81-
then
82-
echo FAIL: the finalizer did not delete the configmap
83-
kubectl logs deployment/memcached-operator
84-
exit 1
85-
fi
128+
operator-sdk migrate
86129

87-
# The deployment should get garbage collected, so we expect to fail getting the deployment.
88-
if ! timeout 20s bash -c -- "while kubectl get deployment ${memcached_deployment}; do sleep 1; done";
130+
if [[ ! -e build/Dockerfile.sdkold ]];
89131
then
90-
kubectl logs deployment/memcached-operator
132+
echo FAIL the old Dockerful should have been renamed to Dockerfile.sdkold
91133
exit 1
92134
fi
93135

136+
dep ensure
137+
# overwrite operator-sdk source with the latest source from the local checkout
138+
pushd vendor/github.com/operator-framework/
139+
rm -Rf operator-sdk/*
140+
cp -a "$ROOTDIR"/{pkg,version,LICENSE} operator-sdk/
141+
popd
142+
143+
operator-sdk build "$DEST_IMAGE"
94144

95-
## TODO enable when this is fixed: https://github.com/operator-framework/operator-sdk/issues/818
96-
# if kubectl logs deployment/memcached-operator | grep -i error;
97-
# then
98-
# echo FAIL: the operator log includes errors
99-
# kubectl logs deployment/memcached-operator
100-
# exit 1
101-
# fi
145+
deploy_operator
146+
test_operator
102147

103148
popd
104149
popd

0 commit comments

Comments
 (0)