Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

commands,pkg/scaffold,hack,pkg/helm: run and migrate command support for helm #897

Merged
merged 7 commits into from
Jan 15, 2019
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ image/build: image/build/ansible image/build/helm
image/build/ansible: build/operator-sdk-dev-x86_64-linux-gnu
./hack/image/build-ansible-image.sh $(ANSIBLE_BASE_IMAGE):dev

image/build/helm:
image/build/helm: build/operator-sdk-dev-x86_64-linux-gnu
./hack/image/build-helm-image.sh $(HELM_BASE_IMAGE):dev

image/push: image/push/ansible image/push/helm
Expand Down
50 changes: 42 additions & 8 deletions commands/operator-sdk/cmd/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"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/helm"
"github.com/operator-framework/operator-sdk/pkg/scaffold/input"

"github.com/spf13/cobra"
Expand All @@ -48,6 +49,8 @@ func migrateRun(cmd *cobra.Command, args []string) {
switch opType {
case projutil.OperatorTypeAnsible:
migrateAnsible()
case projutil.OperatorTypeHelm:
migrateHelm()
default:
log.Fatalf("operator of type %s cannot be migrated.", opType)
}
Expand Down Expand Up @@ -76,14 +79,7 @@ func migrateAnsible() {
log.Fatalf("error trying to stat playbook.yaml: (%v)", err)
}

dockerfilePath := filepath.Join(scaffold.BuildDir, scaffold.DockerfileFile)
newDockerfilePath := dockerfilePath + ".sdkold"
err = os.Rename(dockerfilePath, newDockerfilePath)
if err != nil {
log.Fatalf("failed to rename Dockerfile: (%v)", err)
}
log.Printf("renamed Dockerfile to %s and replaced with newer version", newDockerfilePath)
log.Print("Compare the new Dockerfile to your old one and manually migrate any customizations")
renameDockerfile()

s := &scaffold.Scaffold{}
err = s.Execute(cfg,
Expand All @@ -97,3 +93,41 @@ func migrateAnsible() {
log.Fatalf("add scaffold failed: (%v)", err)
}
}

// migrateHelm runs the migration process for a helm-based operator
func migrateHelm() {
wd := projutil.MustGetwd()

cfg := &input.Config{
AbsProjectPath: wd,
ProjectName: filepath.Base(wd),
}

renameDockerfile()

s := &scaffold.Scaffold{}
err := s.Execute(cfg,
&helm.Main{},
&helm.GopkgToml{},
&helm.DockerfileHybrid{
Watches: true,
HelmCharts: true,
},
&helm.Entrypoint{},
&helm.UserSetup{},
)
if err != nil {
log.Fatalf("add scaffold failed: (%v)", err)
}
}

func renameDockerfile() {
dockerfilePath := filepath.Join(scaffold.BuildDir, scaffold.DockerfileFile)
newDockerfilePath := dockerfilePath + ".sdkold"
err := os.Rename(dockerfilePath, newDockerfilePath)
if err != nil {
log.Fatalf("failed to rename Dockerfile: (%v)", err)
}
log.Printf("renamed Dockerfile to %s and replaced with newer version", newDockerfilePath)
log.Print("Compare the new Dockerfile to your old one and manually migrate any customizations")
}
1 change: 1 addition & 0 deletions commands/operator-sdk/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ func NewRunCmd() *cobra.Command {
}

runCmd.AddCommand(run.NewAnsibleCmd())
runCmd.AddCommand(run.NewHelmCmd())
return runCmd
}
3 changes: 1 addition & 2 deletions commands/operator-sdk/cmd/run/ansible.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ import (
"github.com/spf13/cobra"
)

var flags *aoflags.AnsibleOperatorFlags

// NewAnsibleCmd returns a command that will run an ansible operator
func NewAnsibleCmd() *cobra.Command {
var flags *aoflags.AnsibleOperatorFlags
newCmd := &cobra.Command{
Use: "ansible",
Short: "Runs as an ansible operator",
Expand Down
37 changes: 37 additions & 0 deletions commands/operator-sdk/cmd/run/helm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2019 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 run

import (
"github.com/operator-framework/operator-sdk/pkg/helm"
hoflags "github.com/operator-framework/operator-sdk/pkg/helm/flags"

"github.com/spf13/cobra"
)

// NewHelmCmd returns a command that will run a helm operator
func NewHelmCmd() *cobra.Command {
var flags *hoflags.HelmOperatorFlags
newCmd := &cobra.Command{
Use: "helm",
Short: "Runs as a Helm operator",
Run: func(cmd *cobra.Command, args []string) {
helm.Run(flags)
},
}
flags = hoflags.AddTo(newCmd.Flags())

return newCmd
}
56 changes: 6 additions & 50 deletions commands/operator-sdk/cmd/up/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,17 @@ import (
"strings"
"syscall"

"sigs.k8s.io/controller-runtime/pkg/runtime/signals"

"github.com/operator-framework/operator-sdk/internal/util/projutil"
"github.com/operator-framework/operator-sdk/pkg/ansible"
aoflags "github.com/operator-framework/operator-sdk/pkg/ansible/flags"
"github.com/operator-framework/operator-sdk/pkg/helm/client"
"github.com/operator-framework/operator-sdk/pkg/helm/controller"
"github.com/operator-framework/operator-sdk/pkg/helm"
hoflags "github.com/operator-framework/operator-sdk/pkg/helm/flags"
"github.com/operator-framework/operator-sdk/pkg/helm/release"
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
"github.com/operator-framework/operator-sdk/pkg/scaffold"
sdkVersion "github.com/operator-framework/operator-sdk/version"
"k8s.io/helm/pkg/storage"
"k8s.io/helm/pkg/storage/driver"

log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/manager"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
)

// NewLocalCmd - up local command to run an operator loccally
Expand Down Expand Up @@ -172,49 +163,14 @@ func upLocalHelm() {
log.Fatalf("failed to set %s environment variable: (%v)", k8sutil.KubeConfigEnvVar, err)
}

logf.SetLogger(logf.ZapLogger(false))

printVersion()

cfg, err := config.GetConfig()
if err != nil {
log.Fatal(err)
}

mgr, err := manager.New(cfg, manager.Options{Namespace: namespace})
if err != nil {
log.Fatal(err)
}

// Create Tiller's storage backend and kubernetes client
storageBackend := storage.Init(driver.NewMemory())
tillerKubeClient, err := client.NewFromManager(mgr)
if err != nil {
log.Fatal(err)
}

factories, err := release.NewManagerFactoriesFromFile(storageBackend, tillerKubeClient, helmOperatorFlags.WatchesFile)
if err != nil {
log.Fatal(err)
}

for gvk, factory := range factories {
// Register the controller with the factory.
err := controller.Add(mgr, controller.WatchOptions{
Namespace: namespace,
GVK: gvk,
ManagerFactory: factory,
ReconcilePeriod: helmOperatorFlags.ReconcilePeriod,
})
if err != nil {
log.Fatal(err)
// Set the kubeconfig that the manager will be able to grab
if namespace != "" {
if err := os.Setenv(k8sutil.WatchNamespaceEnvVar, namespace); err != nil {
log.Fatalf("failed to set %s environment variable: (%v)", k8sutil.WatchNamespaceEnvVar, err)
}
}

// Start the Cmd
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
log.Fatal(err)
}
helm.Run(helmOperatorFlags)
}

func printVersion() {
Expand Down
22 changes: 13 additions & 9 deletions doc/dev/testing/travis-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ The Go, Ansible, and Helm tests then differ in what tests they run.
### Ansible tests

1. Run [ansible e2e tests][ansible-e2e].
1. Create base ansible operator image by running [`hack/image/scaffold-ansible-image.go`][ansible-base].
1. Create base ansible operator image by running [`hack/image/ansible/scaffold-ansible-image.go`][ansible-base].
2. Build base ansible operator image.
3. Create and configure a new ansible type memcached-operator.
4. Create cluster resources.
Expand All @@ -86,12 +86,16 @@ The Go, Ansible, and Helm tests then differ in what tests they run.
### Helm Tests

1. Run [helm e2e tests][helm-e2e].
1. Build base helm operator image from [`test/helm-operator`][helm-base].
2. Create and configure a new helm type nginx-operator.
3. Create cluster resources.
4. Wait for operator to be ready.
5. Create nginx CR and wait for it to be ready.
6. Delete nginx CR and verify that finalizer (which writes a message in the operator logs) ran.
1. Create base helm operator image by running [`hack/image/helm/scaffold-helm-image.go`][helm-base].
joelanford marked this conversation as resolved.
Show resolved Hide resolved
2. Build base helm operator image.
3. Create and configure a new helm type nginx-operator.
4. Create cluster resources.
5. Wait for operator to be ready.
6. Create nginx CR and wait for it to be ready.
7. Delete nginx CR and verify that finalizer (which writes a message in the operator logs) ran.
8. Run `operator-sdk migrate` to add go source to the operator.
9. Run `operator-sdk build` to compile the new binary and build a new image.
10. Re-run steps 4-7 to test the migrated operator.

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

Expand All @@ -110,8 +114,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]: ../../../hack/image/scaffold-ansible-image.go
[ansible-base]: ../../../hack/image/ansible/scaffold-ansible-image.go
[helm-e2e]: ../../../hack/tests/e2e-helm.sh
[helm-base]: ../../../test/helm-operator
[helm-base]: ../../../hack/image/helm/scaffold-helm-image.go
[marker-github]: https://github.com/crawford/marker
[marker-local]: ../../../hack/ci/marker
2 changes: 1 addition & 1 deletion hack/image/build-ansible-image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mkdir -p "$BASEIMAGEDIR"

# build operator binary and base image
pushd "$BASEIMAGEDIR"
go run "$ROOTDIR/hack/image/scaffold-ansible-image.go"
go run "$ROOTDIR/hack/image/ansible/scaffold-ansible-image.go"

mkdir -p build/_output/bin/
cp $ROOTDIR/build/operator-sdk-dev-x86_64-linux-gnu build/_output/bin/ansible-operator
Expand Down
17 changes: 14 additions & 3 deletions hack/image/build-helm-image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@

set -eux

source hack/lib/test_lib.sh

ROOTDIR="$(pwd)"
GOTMP="$(mktemp -d -p $GOPATH/src)"
trap_add 'rm -rf $GOTMP' EXIT
BASEIMAGEDIR="$GOTMP/helm-operator"
mkdir -p "$BASEIMAGEDIR"

# build operator binary and base image
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o test/helm-operator/helm-operator test/helm-operator/cmd/helm-operator/main.go
pushd test/helm-operator
docker build -t "$1" .
pushd "$BASEIMAGEDIR"
go run "$ROOTDIR/hack/image/helm/scaffold-helm-image.go"

mkdir -p build/_output/bin/
cp $ROOTDIR/build/operator-sdk-dev-x86_64-linux-gnu build/_output/bin/helm-operator
operator-sdk build $1
popd
45 changes: 45 additions & 0 deletions hack/image/helm/scaffold-helm-image.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2019 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/helm"
"github.com/operator-framework/operator-sdk/pkg/scaffold/input"
)

// main renders scaffolds that are required to build the helm operator base
// image. It is intended for release engineering use only. After running this,
// you can place a binary in `build/_output/bin/helm-operator` and then run
// `operator-sdk build`.
func main() {
cfg := &input.Config{
AbsProjectPath: projutil.MustGetwd(),
ProjectName: "helm-operator",
}

s := &scaffold.Scaffold{}
err := s.Execute(cfg,
&helm.DockerfileHybrid{},
&helm.Entrypoint{},
&helm.UserSetup{},
)
if err != nil {
log.Fatalf("add scaffold failed: (%v)", err)
}
}
Loading