Skip to content

Commit dd62eaa

Browse files
authored
adds migrate and run ansible commands (#887)
adds `migrate` and `run ansible` commands 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`. The `operator-sdk run ansible` command uses the operator-sdk binary as the production-use ansible operator binary. fixes #886
1 parent d826c3c commit dd62eaa

File tree

20 files changed

+647
-181
lines changed

20 files changed

+647
-181
lines changed

commands/operator-sdk/cmd/migrate.go

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright 2019 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+
// NewMigrateCmd returns a command that will add source code to an existing non-go operator
31+
func NewMigrateCmd() *cobra.Command {
32+
return &cobra.Command{
33+
Use: "migrate",
34+
Short: "Adds source code to an operator",
35+
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.`,
36+
Run: migrateRun,
37+
}
38+
}
39+
40+
// migrateRun determines the current operator type and runs the corresponding
41+
// migrate function.
42+
func migrateRun(cmd *cobra.Command, args []string) {
43+
projutil.MustInProjectRoot()
44+
45+
_ = projutil.CheckAndGetProjectGoPkg()
46+
47+
opType := projutil.GetOperatorType()
48+
switch opType {
49+
case projutil.OperatorTypeAnsible:
50+
migrateAnsible()
51+
default:
52+
log.Fatalf("operator of type %s cannot be migrated.", opType)
53+
}
54+
}
55+
56+
// migrateAnsible runs the migration process for an ansible-based operator
57+
func migrateAnsible() {
58+
wd := projutil.MustGetwd()
59+
60+
cfg := &input.Config{
61+
AbsProjectPath: wd,
62+
ProjectName: filepath.Base(wd),
63+
}
64+
65+
dockerfile := ansible.DockerfileHybrid{
66+
Watches: true,
67+
Roles: true,
68+
}
69+
_, err := os.Stat("playbook.yaml")
70+
switch {
71+
case err == nil:
72+
dockerfile.Playbook = true
73+
case os.IsNotExist(err):
74+
log.Print("No playbook was found, so not including it in the new Dockerfile")
75+
default:
76+
log.Fatalf("error trying to stat playbook.yaml: (%v)", err)
77+
}
78+
79+
dockerfilePath := filepath.Join(scaffold.BuildDir, scaffold.DockerfileFile)
80+
newDockerfilePath := dockerfilePath + ".sdkold"
81+
err = os.Rename(dockerfilePath, newDockerfilePath)
82+
if err != nil {
83+
log.Fatalf("failed to rename Dockerfile: (%v)", err)
84+
}
85+
log.Printf("renamed Dockerfile to %s and replaced with newer version", newDockerfilePath)
86+
log.Print("Compare the new Dockerfile to your old one and manually migrate any customizations")
87+
88+
s := &scaffold.Scaffold{}
89+
err = s.Execute(cfg,
90+
&ansible.Main{},
91+
&ansible.GopkgToml{},
92+
&dockerfile,
93+
&ansible.Entrypoint{},
94+
&ansible.UserSetup{},
95+
)
96+
if err != nil {
97+
log.Fatalf("add scaffold failed: (%v)", err)
98+
}
99+
}

commands/operator-sdk/cmd/root.go

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ func NewRootCmd() *cobra.Command {
3535
cmd.AddCommand(NewCompletionCmd())
3636
cmd.AddCommand(NewTestCmd())
3737
cmd.AddCommand(NewPrintDepsCmd())
38+
cmd.AddCommand(NewMigrateCmd())
39+
cmd.AddCommand(NewRunCmd())
3840

3941
return cmd
4042
}

commands/operator-sdk/cmd/run.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2019 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+
"github.com/operator-framework/operator-sdk/commands/operator-sdk/cmd/run"
19+
20+
"github.com/spf13/cobra"
21+
)
22+
23+
// NewRunCmd returns a command that contains subcommands to run specific
24+
// operator types.
25+
func NewRunCmd() *cobra.Command {
26+
runCmd := &cobra.Command{
27+
Use: "run",
28+
Short: "Runs a generic operator",
29+
}
30+
31+
runCmd.AddCommand(run.NewAnsibleCmd())
32+
return runCmd
33+
}
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2019 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 run
16+
17+
import (
18+
"github.com/operator-framework/operator-sdk/pkg/ansible"
19+
aoflags "github.com/operator-framework/operator-sdk/pkg/ansible/flags"
20+
21+
"github.com/spf13/cobra"
22+
)
23+
24+
var flags *aoflags.AnsibleOperatorFlags
25+
26+
// NewAnsibleCmd returns a command that will run an ansible operator
27+
func NewAnsibleCmd() *cobra.Command {
28+
newCmd := &cobra.Command{
29+
Use: "ansible",
30+
Short: "Runs as an ansible operator",
31+
Run: func(cmd *cobra.Command, args []string) {
32+
ansible.Run(flags)
33+
},
34+
}
35+
flags = aoflags.AddTo(newCmd.Flags())
36+
37+
return newCmd
38+
}

commands/operator-sdk/cmd/up/local.go

+7-35
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ import (
2929
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
3030

3131
"github.com/operator-framework/operator-sdk/internal/util/projutil"
32+
"github.com/operator-framework/operator-sdk/pkg/ansible"
3233
"github.com/operator-framework/operator-sdk/pkg/ansible/flags"
33-
ansibleOperator "github.com/operator-framework/operator-sdk/pkg/ansible/operator"
34-
proxy "github.com/operator-framework/operator-sdk/pkg/ansible/proxy"
3534
"github.com/operator-framework/operator-sdk/pkg/helm/client"
3635
"github.com/operator-framework/operator-sdk/pkg/helm/controller"
3736
"github.com/operator-framework/operator-sdk/pkg/helm/release"
@@ -154,41 +153,14 @@ func upLocalAnsible() {
154153
if err := os.Setenv(k8sutil.KubeConfigEnvVar, kubeConfig); err != nil {
155154
log.Fatalf("failed to set %s environment variable: (%v)", k8sutil.KubeConfigEnvVar, err)
156155
}
157-
158-
logf.SetLogger(logf.ZapLogger(false))
159-
160-
mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{Namespace: namespace})
161-
if err != nil {
162-
log.Fatal(err)
163-
}
164-
165-
printVersion()
166-
log.Infof("watching namespace: %s", namespace)
167-
done := make(chan error)
168-
cMap := proxy.NewControllerMap()
169-
170-
// start the proxy
171-
err = proxy.Run(done, proxy.Options{
172-
Address: "localhost",
173-
Port: 8888,
174-
KubeConfig: mgr.GetConfig(),
175-
Cache: mgr.GetCache(),
176-
RESTMapper: mgr.GetRESTMapper(),
177-
ControllerMap: cMap,
178-
})
179-
if err != nil {
180-
log.Fatalf("error starting proxy: (%v)", err)
156+
// Set the kubeconfig that the manager will be able to grab
157+
if namespace != "" {
158+
if err := os.Setenv(k8sutil.WatchNamespaceEnvVar, namespace); err != nil {
159+
log.Fatalf("failed to set %s environment variable: (%v)", k8sutil.WatchNamespaceEnvVar, err)
160+
}
181161
}
182162

183-
// start the operator
184-
go ansibleOperator.Run(done, mgr, ansibleOperatorFlags, cMap)
185-
186-
// wait for either to finish
187-
err = <-done
188-
if err != nil {
189-
log.Fatal(err)
190-
}
191-
log.Info("Exiting.")
163+
ansible.Run(ansibleOperatorFlags)
192164
}
193165

194166
func upLocalHelm() {

doc/dev/testing/travis-build.md

+13-9
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,17 @@ The Go, Ansible, and Helm tests then differ in what tests they run.
6969
### Ansible tests
7070

7171
1. Run [ansible e2e tests][ansible-e2e].
72-
1. Build base ansible operator image from [`test/ansible-operator`][ansible-base].
73-
2. Create and configure a new ansible type memcached-operator.
74-
3. Create cluster resources.
75-
4. Wait for operator to be ready.
76-
5. Create a memcached CR and wait for it to be ready.
77-
6. Create a configmap that the memcached-operator is configured to delete using a finalizer.
78-
7. Delete memcached CR and verify that the finalizer deleted the configmap.
72+
1. Create base ansible operator image by running [`hack/image/scaffold-ansible-image.go`][ansible-base].
73+
2. Build base ansible operator image.
74+
3. Create and configure a new ansible type memcached-operator.
75+
4. Create cluster resources.
76+
5. Wait for operator to be ready.
77+
6. Create a memcached CR and wait for it to be ready.
78+
7. Create a configmap that the memcached-operator is configured to delete using a finalizer.
79+
8. Delete memcached CR and verify that the finalizer deleted the configmap.
80+
9. Run `operator-sdk migrate` to add go source to the operator.
81+
10. Run `operator-sdk build` to compile the new binary and build a new image.
82+
11. Re-run steps 4-8 to test the migrated operator.
7983

8084
**NOTE**: All created resources, including the namespace, are deleted using a bash trap when the test finishes
8185

@@ -106,8 +110,8 @@ The markdown test does not create a new cluster and runs in a barebones travis V
106110
[go-e2e]: ../../../hack/tests/e2e-go.sh
107111
[tls-tests]: ../../../test/e2e/tls_util_test.go
108112
[ansible-e2e]: ../../../hack/tests/e2e-ansible.sh
109-
[ansible-base]: ../../../test/ansible-operator
113+
[ansible-base]: ../../../hack/image/scaffold-ansible-image.go
110114
[helm-e2e]: ../../../hack/tests/e2e-helm.sh
111115
[helm-base]: ../../../test/helm-operator
112116
[marker-github]: https://github.com/crawford/marker
113-
[marker-local]: ../../../hack/ci/marker
117+
[marker-local]: ../../../hack/ci/marker

hack/image/build-ansible-image.sh

+14-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,19 @@
22

33
set -eux
44

5+
source hack/lib/test_lib.sh
6+
7+
ROOTDIR="$(pwd)"
8+
GOTMP="$(mktemp -d -p $GOPATH/src)"
9+
trap_add 'rm -rf $GOTMP' EXIT
10+
BASEIMAGEDIR="$GOTMP/ansible-operator"
11+
mkdir -p "$BASEIMAGEDIR"
12+
513
# build operator binary and base image
6-
go build -o test/ansible-operator/ansible-operator test/ansible-operator/cmd/ansible-operator/main.go
7-
pushd test/ansible-operator
8-
docker build -t "$1" .
14+
pushd "$BASEIMAGEDIR"
15+
go run "$ROOTDIR/hack/image/scaffold-ansible-image.go"
16+
17+
mkdir -p build/_output/bin/
18+
cp $(which operator-sdk) build/_output/bin/ansible-operator
19+
operator-sdk build $1
920
popd

hack/image/scaffold-ansible-image.go

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2019 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 place a binary in `build/_output/bin/ansible-operator` and then run
29+
// `operator-sdk build`.
30+
func main() {
31+
cfg := &input.Config{
32+
AbsProjectPath: projutil.MustGetwd(),
33+
ProjectName: "ansible-operator",
34+
}
35+
36+
s := &scaffold.Scaffold{}
37+
err := s.Execute(cfg,
38+
&ansible.DockerfileHybrid{},
39+
&ansible.Entrypoint{},
40+
&ansible.UserSetup{},
41+
)
42+
if err != nil {
43+
log.Fatalf("add scaffold failed: (%v)", err)
44+
}
45+
}

0 commit comments

Comments
 (0)