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

cmd/operator-sdk/add/controller.go: support built-in k8s API controllers #1344

Merged
merged 11 commits into from
May 17, 2019
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- New option for [`operator-sdk build --image-builder`](https://github.com/operator-framework/operator-sdk/blob/master/doc/sdk-cli-reference.md#build), which can be used to specify which image builder to use. Adds support for [buildah](https://github.com/containers/buildah/). ([#1311](https://github.com/operator-framework/operator-sdk/pull/1311))
- Manager is now configured with a new `DynamicRESTMapper`, which accounts for the fact that the default `RESTMapper`, which only checks resource types at startup, can't handle the case of first creating a CRD and then an instance of that CRD. ([#1329](https://github.com/operator-framework/operator-sdk/pull/1329))
- New optional flags `--k8s-api` and `--k8s-import-path` for [`operator-sdk add controller`](https://github.com/operator-framework/operator-sdk/blob/master/doc/sdk-cli-reference.md#controller) to specify that the new controller reconciles a built-in Kubernetes API. ([#1344](https://github.com/operator-framework/operator-sdk/pull/1344))

### Changed

Expand Down
15 changes: 13 additions & 2 deletions cmd/operator-sdk/add/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ import (
"github.com/spf13/cobra"
)

var (
k8sAPI bool
k8sImportPath string
)

func newAddControllerCmd() *cobra.Command {
controllerCmd := &cobra.Command{
Use: "controller",
Expand Down Expand Up @@ -57,6 +62,8 @@ Example:
if err := controllerCmd.MarkFlagRequired("kind"); err != nil {
log.Fatalf("Failed to mark `kind` flag for `add controller` subcommand as required")
}
controllerCmd.Flags().StringVar(&k8sImportPath, "k8s-import-path", "k8s.io/api", "Kubernetes resource import path. Only valid if --k8s-api is set")
estroz marked this conversation as resolved.
Show resolved Hide resolved
controllerCmd.Flags().BoolVar(&k8sAPI, "k8s-api", false, "The provided kind for api-version is a Kubernetes resource API")

return controllerCmd
}
Expand All @@ -81,10 +88,14 @@ func controllerRun(cmd *cobra.Command, args []string) error {
Repo: projutil.CheckAndGetProjectGoPkg(),
AbsProjectPath: projutil.MustGetwd(),
}

s := &scaffold.Scaffold{}

ck := &scaffold.ControllerKind{Resource: r}
if k8sAPI {
ck.K8sImportPath = k8sImportPath
}
err = s.Execute(cfg,
&scaffold.ControllerKind{Resource: r},
ck,
&scaffold.AddController{Resource: r},
)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions doc/sdk-cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,8 @@ Adds a new controller under `pkg/controller/<kind>/...` that, by default, reconc

* `--api-version` string - CRD APIVersion in the format `$GROUP_NAME/$VERSION` (e.g app.example.com/v1alpha1)
* `--kind` string - CRD Kind. (e.g AppService)
* `--k8s-api` - The provided kind for api-version is a Kubernetes resource API
* `--k8s-import-path` - Kubernetes resource import path. Only valid if --k8s-api is set (default `k8s.io/api`)

#### Example

Expand Down
52 changes: 37 additions & 15 deletions internal/pkg/scaffold/controller_kind.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package scaffold

import (
"path"
"path/filepath"

"github.com/operator-framework/operator-sdk/internal/pkg/scaffold/input"
Expand All @@ -26,6 +27,12 @@ type ControllerKind struct {

// Resource defines the inputs for the controller's primary resource
Resource *Resource
// K8sImportPath holds the import path for a built-in Kubernetes API that
// this controller reconciles if specified by the scaffold invoker.
K8sImportPath string
// ImportMap maps all imports destined for the scaffold to their import
// identifier, if any.
ImportMap map[string]string
}

func (s *ControllerKind) GetInput() (input.Input, error) {
Expand All @@ -36,29 +43,44 @@ func (s *ControllerKind) GetInput() (input.Input, error) {
// Error if this file exists.
s.IfExistsAction = input.Error
s.TemplateBody = controllerKindTemplate

// Set imports.
if len(s.ImportMap) == 0 {
estroz marked this conversation as resolved.
Show resolved Hide resolved
s.ImportMap = controllerKindImports
}
importPrefix := path.Join(s.Repo, "pkg", "apis")
if s.K8sImportPath != "" {
importPrefix = s.K8sImportPath
}
importPath := path.Join(importPrefix, s.Resource.GoImportGroup, s.Resource.Version)
s.ImportMap[importPath] = s.Resource.GoImportGroup + s.Resource.Version
return s.Input, nil
}

var controllerKindImports = map[string]string{
"k8s.io/api/core/v1": "corev1",
"k8s.io/apimachinery/pkg/api/errors": "",
"k8s.io/apimachinery/pkg/apis/meta/v1": "metav1",
"k8s.io/apimachinery/pkg/runtime": "",
"k8s.io/apimachinery/pkg/types": "",
"sigs.k8s.io/controller-runtime/pkg/client": "",
"sigs.k8s.io/controller-runtime/pkg/controller": "",
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil": "",
"sigs.k8s.io/controller-runtime/pkg/handler": "",
"sigs.k8s.io/controller-runtime/pkg/manager": "",
"sigs.k8s.io/controller-runtime/pkg/reconcile": "",
"sigs.k8s.io/controller-runtime/pkg/runtime/log": "logf",
"sigs.k8s.io/controller-runtime/pkg/source": "",
}

const controllerKindTemplate = `package {{ .Resource.LowerKind }}

import (
"context"

{{ .Resource.GoImportGroup}}{{ .Resource.Version }} "{{ .Repo }}/pkg/apis/{{ .Resource.GoImportGroup}}/{{ .Resource.Version }}"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
"sigs.k8s.io/controller-runtime/pkg/source"
{{range $p, $i := .ImportMap -}}
{{$i}} "{{$p}}"
{{end}}
)

var log = logf.Log.WithName("controller_{{ .Resource.LowerKind }}")
Expand Down
1 change: 0 additions & 1 deletion internal/pkg/scaffold/controller_kind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import (
"context"

appv1alpha1 "github.com/example-inc/app-operator/pkg/apis/app/v1alpha1"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down