From 432ab80e3162c005a405248957d51489be6a4e6b Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Wed, 7 Nov 2018 13:45:06 -0500 Subject: [PATCH 01/24] Renamed all occurance of "example" to "console". Regenerate pkg/generated/ --- Dockerfile | 4 +- cmd/{example => console}/main.go | 15 +- glide.yaml | 2 +- hack/lib/constants.sh | 6 +- hack/update-codegen.sh | 4 +- install/config.yaml | 2 +- install/cr.yaml | 37 +++- manifests/00-crd.yaml | 12 +- pkg/apis/{example => console}/install.go | 6 +- pkg/apis/{example => console}/v1alpha1/doc.go | 2 +- .../{example => console}/v1alpha1/register.go | 6 +- .../{example => console}/v1alpha1/types.go | 14 +- .../v1alpha1/zz_generated.deepcopy.go | 38 ++--- pkg/cmd/operator/cmd.go | 13 +- pkg/cmd/version/cmd.go | 1 + pkg/{example => console}/operator/operator.go | 26 +-- pkg/console/starter/starter.go | 108 ++++++++++++ pkg/{example => console}/version/version.go | 0 pkg/example/starter/starter.go | 61 ------- .../clientset/versioned/clientset.go | 26 +-- .../versioned/fake/clientset_generated.go | 18 +- .../clientset/versioned/fake/register.go | 4 +- .../clientset/versioned/scheme/register.go | 4 +- .../typed/console/v1alpha1/console.go | 158 ++++++++++++++++++ .../typed/console/v1alpha1/console_client.go | 74 ++++++++ .../{example => console}/v1alpha1/doc.go | 0 .../{example => console}/v1alpha1/fake/doc.go | 0 .../console/v1alpha1/fake/fake_console.go | 124 ++++++++++++++ .../v1alpha1/fake/fake_console_client.go | 24 +++ .../v1alpha1/generated_expansion.go | 2 +- .../typed/example/v1alpha1/example_client.go | 74 -------- .../typed/example/v1alpha1/exampleoperator.go | 158 ------------------ .../v1alpha1/fake/fake_example_client.go | 24 --- .../v1alpha1/fake/fake_exampleoperator.go | 124 -------------- .../{example => console}/interface.go | 6 +- .../console/v1alpha1/console.go | 73 ++++++++ .../v1alpha1/interface.go | 12 +- .../example/v1alpha1/exampleoperator.go | 73 -------- .../informers/externalversions/factory.go | 12 +- .../informers/externalversions/generic.go | 8 +- .../internalinterfaces/factory_interfaces.go | 2 +- .../listers/console/v1alpha1/console.go | 78 +++++++++ .../console/v1alpha1/expansion_generated.go | 11 ++ .../example/v1alpha1/exampleoperator.go | 78 --------- .../example/v1alpha1/expansion_generated.go | 11 -- 45 files changed, 806 insertions(+), 729 deletions(-) rename cmd/{example => console}/main.go (77%) rename pkg/apis/{example => console}/install.go (71%) rename pkg/apis/{example => console}/v1alpha1/doc.go (71%) rename pkg/apis/{example => console}/v1alpha1/register.go (92%) rename pkg/apis/{example => console}/v1alpha1/types.go (65%) rename pkg/apis/{example => console}/v1alpha1/zz_generated.deepcopy.go (66%) create mode 100644 pkg/cmd/version/cmd.go rename pkg/{example => console}/operator/operator.go (83%) create mode 100644 pkg/console/starter/starter.go rename pkg/{example => console}/version/version.go (100%) delete mode 100644 pkg/example/starter/starter.go create mode 100644 pkg/generated/clientset/versioned/typed/console/v1alpha1/console.go create mode 100644 pkg/generated/clientset/versioned/typed/console/v1alpha1/console_client.go rename pkg/generated/clientset/versioned/typed/{example => console}/v1alpha1/doc.go (100%) rename pkg/generated/clientset/versioned/typed/{example => console}/v1alpha1/fake/doc.go (100%) create mode 100644 pkg/generated/clientset/versioned/typed/console/v1alpha1/fake/fake_console.go create mode 100644 pkg/generated/clientset/versioned/typed/console/v1alpha1/fake/fake_console_client.go rename pkg/generated/clientset/versioned/typed/{example => console}/v1alpha1/generated_expansion.go (60%) delete mode 100644 pkg/generated/clientset/versioned/typed/example/v1alpha1/example_client.go delete mode 100644 pkg/generated/clientset/versioned/typed/example/v1alpha1/exampleoperator.go delete mode 100644 pkg/generated/clientset/versioned/typed/example/v1alpha1/fake/fake_example_client.go delete mode 100644 pkg/generated/clientset/versioned/typed/example/v1alpha1/fake/fake_exampleoperator.go rename pkg/generated/informers/externalversions/{example => console}/interface.go (77%) create mode 100644 pkg/generated/informers/externalversions/console/v1alpha1/console.go rename pkg/generated/informers/externalversions/{example => console}/v1alpha1/interface.go (57%) delete mode 100644 pkg/generated/informers/externalversions/example/v1alpha1/exampleoperator.go create mode 100644 pkg/generated/listers/console/v1alpha1/console.go create mode 100644 pkg/generated/listers/console/v1alpha1/expansion_generated.go delete mode 100644 pkg/generated/listers/example/v1alpha1/exampleoperator.go delete mode 100644 pkg/generated/listers/example/v1alpha1/expansion_generated.go diff --git a/Dockerfile b/Dockerfile index b266f05..f91bf49 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -# This is an example operator. +# This is an console operator. # -# The standard name for its image is enj/example-operator +# The standard name for its image is enj/console-operator # FROM openshift/origin-release:golang-1.10 COPY . /go/src/github.com/enj/example-operator diff --git a/cmd/example/main.go b/cmd/console/main.go similarity index 77% rename from cmd/example/main.go rename to cmd/console/main.go index 984b5fa..295bc62 100644 --- a/cmd/example/main.go +++ b/cmd/console/main.go @@ -1,19 +1,20 @@ package main import ( + // standard lib goflag "flag" "fmt" "math/rand" "os" "time" - + // 3rd party "github.com/spf13/cobra" "github.com/spf13/pflag" - + // kube / openshift utilflag "k8s.io/apiserver/pkg/util/flag" "k8s.io/apiserver/pkg/util/logs" - - "github.com/enj/example-operator/pkg/cmd/operator" + // us + "github.com/openshift/console-operator/pkg/cmd/operator" ) func main() { @@ -25,16 +26,16 @@ func main() { logs.InitLogs() defer logs.FlushLogs() - command := NewExampleCommand() + command := NewOperatorCommand() if err := command.Execute(); err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(1) } } -func NewExampleCommand() *cobra.Command { +func NewOperatorCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "example", + Use: "console", Short: "Top level command", Run: func(cmd *cobra.Command, args []string) { cmd.Help() diff --git a/glide.yaml b/glide.yaml index 9d75c2c..a7acb57 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,4 +1,4 @@ -package: github.com/enj/example-operator +package: github.com/enj/console-operator import: # kube diff --git a/hack/lib/constants.sh b/hack/lib/constants.sh index 94f2c99..4a8c96e 100755 --- a/hack/lib/constants.sh +++ b/hack/lib/constants.sh @@ -2,7 +2,7 @@ # This script provides constants for the Golang binary build process -readonly OS_GO_PACKAGE=github.com/enj/example-operator +readonly OS_GO_PACKAGE=github.com/openshift/console-operator readonly OS_BUILD_ENV_GOLANG="${OS_BUILD_ENV_GOLANG:-1.9}" readonly OS_BUILD_ENV_IMAGE="${OS_BUILD_ENV_IMAGE:-openshift/origin-release:golang-${OS_BUILD_ENV_GOLANG}}" @@ -25,7 +25,7 @@ readonly OS_GOFLAGS_TAGS="include_gcs include_oss containers_image_openpgp" readonly OS_IMAGE_COMPILE_BINARIES=( ) readonly OS_CROSS_COMPILE_TARGETS=( - cmd/example + cmd/console ) readonly OS_CROSS_COMPILE_BINARIES=("${OS_CROSS_COMPILE_TARGETS[@]##*/}") @@ -146,5 +146,5 @@ readonly OS_ALL_IMAGES=( # os::build::images builds all images in this repo. function os::build::images() { tag_prefix="${OS_IMAGE_PREFIX:-"openshift/origin"}" - os::build::image "${tag_prefix}-example" . + os::build::image "${tag_prefix}-console" . } diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index eeddda1..59fe669 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -29,8 +29,8 @@ verify="${VERIFY:-}" # k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir # instead of the $GOPATH directly. For normal projects this can be dropped. ${CODEGEN_PKG}/generate-groups.sh "all" \ - github.com/enj/example-operator/pkg/generated github.com/enj/example-operator/pkg/apis \ - example:v1alpha1 \ + github.com/openshift/console-operator/pkg/generated github.com/openshift/console-operator/pkg/apis \ + console:v1alpha1 \ --output-base "$(dirname ${BASH_SOURCE})/../../../.." \ --go-header-file ${SCRIPT_ROOT}/hack/boilerplate.txt \ ${verify} diff --git a/install/config.yaml b/install/config.yaml index 54ae484..3cc6062 100644 --- a/install/config.yaml +++ b/install/config.yaml @@ -1,4 +1,4 @@ apiVersion: operator.openshift.io/v1alpha1 kind: GenericOperatorConfig leaderElection: - namespace: example-operator + namespace: console-operator diff --git a/install/cr.yaml b/install/cr.yaml index e5a22da..0b83879 100644 --- a/install/cr.yaml +++ b/install/cr.yaml @@ -1,9 +1,36 @@ -apiVersion: exampleoperator.crd.monis.app/v1alpha1 -kind: ExampleOperator +apiVersion: console.openshift.io/v1alpha1 +kind: Console metadata: - name: example-operator-resource - namespace: example-operator + name: console-operator-resource + namespace: openshift-console spec: managementState: Managed version: 3.10.0 - value: panda + value: this-is-actually-a-key-with-a-random-bytes-value + count: 1 + logging: + level: 0 + +# this is the old one. +# remove soon. +# +## The console-operator will create a console automatically on startup if one does not exist. +## This file is an example of a console resource. +## You may edit this file and `oc apply -f cr.yaml` to make changes to the console. +#apiVersion: "console.openshift.io/v1alpha1" +#kind: "Console" +#metadata: +# # Do not change the name, the operator explicitly requires this name to match as the console is a singleton. +# name: openshift-console +# namespace: openshift-console +#spec: +# # openshift/api/operator/v1alpha1/types.go +# # managementState indicates whether the operator is: +# # - Managed indicates the operator fully manages the state of the console and its sub-resources +# # - Unmanaged indicates that the operator should idle and ignore the console and its sub-resources +# # - Removed indicates that the operator should delete all of the sub-resources of the console +# managementState: Managed +# # there should be only one console at this time +# count: 1 +# logging: +# level: 0 diff --git a/manifests/00-crd.yaml b/manifests/00-crd.yaml index 14b5210..c398805 100644 --- a/manifests/00-crd.yaml +++ b/manifests/00-crd.yaml @@ -1,13 +1,13 @@ apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: - name: exampleoperators.exampleoperator.crd.monis.app + name: consoles.console.openshift.io spec: - group: exampleoperator.crd.monis.app + group: console.openshift.io names: - kind: ExampleOperator - listKind: ExampleOperatorList - plural: exampleoperators - singular: exampleoperator + kind: Console + listKind: ConsoleList + plural: consoles + singular: console scope: Namespaced version: v1alpha1 diff --git a/pkg/apis/example/install.go b/pkg/apis/console/install.go similarity index 71% rename from pkg/apis/example/install.go rename to pkg/apis/console/install.go index f25dd3c..34ddade 100644 --- a/pkg/apis/example/install.go +++ b/pkg/apis/console/install.go @@ -4,15 +4,15 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - examplev1alpha1 "github.com/enj/example-operator/pkg/apis/example/v1alpha1" + consolev1alpha1 "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" ) const ( - GroupName = "exampleoperator.crd.monis.app" + GroupName = "console.openshift.io" ) var ( - schemeBuilder = runtime.NewSchemeBuilder(examplev1alpha1.Install) + schemeBuilder = runtime.NewSchemeBuilder(consolev1alpha1.Install) // Install is a function which adds every version of this group to a scheme Install = schemeBuilder.AddToScheme ) diff --git a/pkg/apis/example/v1alpha1/doc.go b/pkg/apis/console/v1alpha1/doc.go similarity index 71% rename from pkg/apis/example/v1alpha1/doc.go rename to pkg/apis/console/v1alpha1/doc.go index ba0f904..da4e40d 100644 --- a/pkg/apis/example/v1alpha1/doc.go +++ b/pkg/apis/console/v1alpha1/doc.go @@ -2,6 +2,6 @@ // +k8s:defaulter-gen=TypeMeta // +k8s:openapi-gen=true -// +groupName=exampleoperator.crd.monis.app +// +groupName=console.openshift.io package v1alpha1 diff --git a/pkg/apis/example/v1alpha1/register.go b/pkg/apis/console/v1alpha1/register.go similarity index 92% rename from pkg/apis/example/v1alpha1/register.go rename to pkg/apis/console/v1alpha1/register.go index 1d35dc2..15d4030 100644 --- a/pkg/apis/example/v1alpha1/register.go +++ b/pkg/apis/console/v1alpha1/register.go @@ -10,7 +10,7 @@ import ( ) var ( - GroupName = "exampleoperator.crd.monis.app" + GroupName = "console.openshift.io" GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, configv1.Install, operatorsv1alpha1api.Install) // Install is a function which adds this version to a scheme @@ -32,8 +32,8 @@ func Resource(resource string) schema.GroupResource { func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(GroupVersion, - &ExampleOperator{}, - &ExampleOperatorList{}, + &Console{}, + &ConsoleList{}, ) metav1.AddToGroupVersion(scheme, GroupVersion) diff --git a/pkg/apis/example/v1alpha1/types.go b/pkg/apis/console/v1alpha1/types.go similarity index 65% rename from pkg/apis/example/v1alpha1/types.go rename to pkg/apis/console/v1alpha1/types.go index cd268a9..24ee950 100644 --- a/pkg/apis/example/v1alpha1/types.go +++ b/pkg/apis/console/v1alpha1/types.go @@ -9,29 +9,29 @@ import ( // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type ExampleOperator struct { +type Console struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec ExampleOperatorSpec `json:"spec,omitempty"` - Status ExampleOperatorStatus `json:"status,omitempty"` + Spec ConsoleSpec `json:"spec,omitempty"` + Status ConsoleStatus `json:"status,omitempty"` } -type ExampleOperatorSpec struct { +type ConsoleSpec struct { v1alpha1.OperatorSpec Value string `json:"value,omitempty"` } -type ExampleOperatorStatus struct { +type ConsoleStatus struct { v1alpha1.OperatorStatus } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type ExampleOperatorList struct { +type ConsoleList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` - Items []ExampleOperator `json:"items"` + Items []Console `json:"items"` } diff --git a/pkg/apis/example/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/console/v1alpha1/zz_generated.deepcopy.go similarity index 66% rename from pkg/apis/example/v1alpha1/zz_generated.deepcopy.go rename to pkg/apis/console/v1alpha1/zz_generated.deepcopy.go index 7a65fde..a7afc85 100644 --- a/pkg/apis/example/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/console/v1alpha1/zz_generated.deepcopy.go @@ -9,7 +9,7 @@ import ( ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExampleOperator) DeepCopyInto(out *ExampleOperator) { +func (in *Console) DeepCopyInto(out *Console) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) @@ -18,18 +18,18 @@ func (in *ExampleOperator) DeepCopyInto(out *ExampleOperator) { return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExampleOperator. -func (in *ExampleOperator) DeepCopy() *ExampleOperator { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Console. +func (in *Console) DeepCopy() *Console { if in == nil { return nil } - out := new(ExampleOperator) + out := new(Console) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ExampleOperator) DeepCopyObject() runtime.Object { +func (in *Console) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -37,13 +37,13 @@ func (in *ExampleOperator) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExampleOperatorList) DeepCopyInto(out *ExampleOperatorList) { +func (in *ConsoleList) DeepCopyInto(out *ConsoleList) { *out = *in out.TypeMeta = in.TypeMeta out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]ExampleOperator, len(*in)) + *out = make([]Console, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -51,18 +51,18 @@ func (in *ExampleOperatorList) DeepCopyInto(out *ExampleOperatorList) { return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExampleOperatorList. -func (in *ExampleOperatorList) DeepCopy() *ExampleOperatorList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsoleList. +func (in *ConsoleList) DeepCopy() *ConsoleList { if in == nil { return nil } - out := new(ExampleOperatorList) + out := new(ConsoleList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ExampleOperatorList) DeepCopyObject() runtime.Object { +func (in *ConsoleList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -70,35 +70,35 @@ func (in *ExampleOperatorList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExampleOperatorSpec) DeepCopyInto(out *ExampleOperatorSpec) { +func (in *ConsoleSpec) DeepCopyInto(out *ConsoleSpec) { *out = *in out.OperatorSpec = in.OperatorSpec return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExampleOperatorSpec. -func (in *ExampleOperatorSpec) DeepCopy() *ExampleOperatorSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsoleSpec. +func (in *ConsoleSpec) DeepCopy() *ConsoleSpec { if in == nil { return nil } - out := new(ExampleOperatorSpec) + out := new(ConsoleSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExampleOperatorStatus) DeepCopyInto(out *ExampleOperatorStatus) { +func (in *ConsoleStatus) DeepCopyInto(out *ConsoleStatus) { *out = *in in.OperatorStatus.DeepCopyInto(&out.OperatorStatus) return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExampleOperatorStatus. -func (in *ExampleOperatorStatus) DeepCopy() *ExampleOperatorStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsoleStatus. +func (in *ConsoleStatus) DeepCopy() *ConsoleStatus { if in == nil { return nil } - out := new(ExampleOperatorStatus) + out := new(ConsoleStatus) in.DeepCopyInto(out) return out } diff --git a/pkg/cmd/operator/cmd.go b/pkg/cmd/operator/cmd.go index ce82245..5032e68 100644 --- a/pkg/cmd/operator/cmd.go +++ b/pkg/cmd/operator/cmd.go @@ -1,20 +1,21 @@ package operator import ( + // 3rd party "github.com/spf13/cobra" - + // kube / openshift "github.com/openshift/library-go/pkg/controller/controllercmd" - - "github.com/enj/example-operator/pkg/example/starter" - "github.com/enj/example-operator/pkg/example/version" + // us + "github.com/openshift/console-operator/pkg/console/starter" + "github.com/openshift/console-operator/pkg/console/version" ) func NewOperator() *cobra.Command { cmd := controllercmd. - NewControllerCommandConfig("example-operator", version.Get(), starter.RunOperator). + NewControllerCommandConfig("console-operator", version.Get(), starter.RunOperator). NewCommand() cmd.Use = "operator" - cmd.Short = "Start the Example Operator" + cmd.Short = "Start the Console Operator" return cmd } diff --git a/pkg/cmd/version/cmd.go b/pkg/cmd/version/cmd.go new file mode 100644 index 0000000..f37d99d --- /dev/null +++ b/pkg/cmd/version/cmd.go @@ -0,0 +1 @@ +package version diff --git a/pkg/example/operator/operator.go b/pkg/console/operator/operator.go similarity index 83% rename from pkg/example/operator/operator.go rename to pkg/console/operator/operator.go index bb2c5d2..1d277e8 100644 --- a/pkg/example/operator/operator.go +++ b/pkg/console/operator/operator.go @@ -19,36 +19,36 @@ import ( "github.com/openshift/library-go/pkg/operator/resource/resourceapply" "github.com/openshift/library-go/pkg/operator/versioning" - "github.com/enj/example-operator/pkg/controller" - "github.com/enj/example-operator/pkg/generated/clientset/versioned/typed/example/v1alpha1" - exampleinformers "github.com/enj/example-operator/pkg/generated/informers/externalversions/example/v1alpha1" + "github.com/openshift/console-operator/pkg/controller" + "github.com/openshift/console-operator/pkg/generated/clientset/versioned/typed/console/v1alpha1" + consoleinformers "github.com/openshift/console-operator/pkg/generated/informers/externalversions/console/v1alpha1" ) const ( // TargetNamespace could be made configurable if desired - TargetNamespace = "example-operator" + TargetNamespace = "openshift-console" // ResourceName could be made configurable if desired // all resources share the same name to make it easier to reason about and to configure single item watches - ResourceName = "example-operator-resource" + ResourceName = "console-operator-resource" // workQueueKey is the singleton key shared by all events // the value is irrelevant workQueueKey = "key" ) -func NewExampleOperator(eoi exampleinformers.ExampleOperatorInformer, si v1.SecretInformer, operatorClient v1alpha1.ExampleOperatorInterface, secretsClient coreclientv1.SecretsGetter) *ExampleOperator { - c := &ExampleOperator{ +func NewConsoleOperator(coi consoleinformers.ConsoleInformer, si v1.SecretInformer, operatorClient v1alpha1.ConsoleInterface, secretsClient coreclientv1.SecretsGetter) *ConsoleOperator { + c := &ConsoleOperator{ operatorClient: operatorClient, secretsClient: secretsClient, } - operatorInformer := eoi.Informer() + operatorInformer := coi.Informer() secretsInformer := si.Informer() // we do not really need to wait for our informers to sync since we only watch a single resource // and make live reads but it does not hurt anything and guarantees we have the correct behavior - internalController, queue := controller.New("ExampleOperator", c.sync, operatorInformer.HasSynced, secretsInformer.HasSynced) + internalController, queue := controller.New("Console", c.sync, operatorInformer.HasSynced, secretsInformer.HasSynced) c.controller = internalController @@ -70,23 +70,23 @@ func eventHandler(queue workqueue.RateLimitingInterface) cache.ResourceEventHand } } -type ExampleOperator struct { +type ConsoleOperator struct { // for a performance sensitive operator, it would make sense to use informers // to handle reads and clients to handle writes. since this operator works // on a singleton resource, it has no performance requirements. - operatorClient v1alpha1.ExampleOperatorInterface + operatorClient v1alpha1.ConsoleInterface secretsClient coreclientv1.SecretsGetter controller *controller.Controller } -func (c *ExampleOperator) Run(stopCh <-chan struct{}) { +func (c *ConsoleOperator) Run(stopCh <-chan struct{}) { // only start one worker because we only have one key name in our queue // since this operator works on a singleton, it does not make sense to ever run more than one worker c.controller.Run(1, stopCh) } -func (c *ExampleOperator) sync(_ interface{}) error { +func (c *ConsoleOperator) sync(_ interface{}) error { // we ignore the passed in key because it will always be workQueueKey // it does not matter how the sync loop was triggered // all we need to worry about is reconciling the state back to what we expect diff --git a/pkg/console/starter/starter.go b/pkg/console/starter/starter.go new file mode 100644 index 0000000..45a9c1b --- /dev/null +++ b/pkg/console/starter/starter.go @@ -0,0 +1,108 @@ +package starter + +import ( + "fmt" + "github.com/openshift/library-go/pkg/operator/status" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/tools/cache" + "time" + + "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + + "github.com/openshift/console-operator/pkg/console/operator" + "github.com/openshift/console-operator/pkg/generated/clientset/versioned" + "github.com/openshift/console-operator/pkg/generated/informers/externalversions" +) + +func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { + kubeClient, err := kubernetes.NewForConfig(clientConfig) + if err != nil { + return err + } + + consoleOperatorClient, err := versioned.NewForConfig(clientConfig) + if err != nil { + return err + } + + const resync = 10 * time.Minute + + // only watch a specific resource name + tweakListOptions := func(options *v1.ListOptions) { + options.FieldSelector = fields.OneTermEqualSelector("metadata.name", operator.ResourceName).String() + } + + kubeInformersNamespaced := informers.NewSharedInformerFactoryWithOptions(kubeClient, resync, + informers.WithNamespace(operator.TargetNamespace), + informers.WithTweakListOptions(tweakListOptions), + ) + + consoleOperatorInformers := externalversions.NewSharedInformerFactoryWithOptions(consoleOperatorClient, resync, + externalversions.WithNamespace(operator.TargetNamespace), + externalversions.WithTweakListOptions(tweakListOptions), + ) + + consoleOperator := operator.NewConsoleOperator( + consoleOperatorInformers.Console().V1alpha1().Consoles(), + kubeInformersNamespaced.Core().V1().Secrets(), + consoleOperatorClient.ConsoleV1alpha1().Consoles(operator.TargetNamespace), + kubeClient.CoreV1(), + ) + + kubeInformersNamespaced.Start(stopCh) + consoleOperatorInformers.Start(stopCh) + + go consoleOperator.Run(stopCh) + + // prob move this up... + dynamicClient, err := dynamic.NewForConfig(clientConfig) + if err != nil { + return err + } + + // TODO: create the status here.... + // to test this, will need to update STATUS on my CR + // and then check and see if it is updated on the other deal. + // TODO: install this, from the old console-operator install operatorstatus.openshift.io + //clusterOperatorStatus := status.NewClusterOperatorStatusController( + // // what are these? name of controller(operator)? wire this up. + // "openshift-apiserver", + // "openshift-apiserver", + // // what is this + // dynamicClient, + // &operatorStatusProvider{informers: operatorConfigInformers}, + //) + // + //// TODO: will have a series of runs here + //go clusterOperatorStatus.Run(1, stopCh) + + <-stopCh + + return fmt.Errorf("stopped") +} + + + +// Interface +//type operatorStatusProvider struct { +// informers operatorclientinformers.SharedInformerFactory +//} +// +//func (p *operatorStatusProvider) Informer() cache.SharedIndexInformer { +// // TODO: return my informaer.... +// // return p.informers.Openshiftapiserver().V1alpha1().OpenShiftAPIServerOperatorConfigs().Informer() +//} +// +//func (p *operatorStatusProvider) CurrentStatus() (operatorv1alpha1.OperatorStatus, error) { +// // TODO: use my informer to get my status +// instance, err := p.informers.Openshiftapiserver().V1alpha1().OpenShiftAPIServerOperatorConfigs().Lister().Get("instance") +// if err != nil { +// return operatorv1alpha1.OperatorStatus{}, err +// } +// +// return instance.Status.OperatorStatus, nil +//} diff --git a/pkg/example/version/version.go b/pkg/console/version/version.go similarity index 100% rename from pkg/example/version/version.go rename to pkg/console/version/version.go diff --git a/pkg/example/starter/starter.go b/pkg/example/starter/starter.go deleted file mode 100644 index a9a1350..0000000 --- a/pkg/example/starter/starter.go +++ /dev/null @@ -1,61 +0,0 @@ -package starter - -import ( - "fmt" - "time" - - "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/fields" - "k8s.io/client-go/informers" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - - "github.com/enj/example-operator/pkg/example/operator" - "github.com/enj/example-operator/pkg/generated/clientset/versioned" - "github.com/enj/example-operator/pkg/generated/informers/externalversions" -) - -func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { - kubeClient, err := kubernetes.NewForConfig(clientConfig) - if err != nil { - return err - } - - exampleOperatorClient, err := versioned.NewForConfig(clientConfig) - if err != nil { - return err - } - - const resync = 10 * time.Minute - - // only watch a specific resource name - tweakListOptions := func(options *v1.ListOptions) { - options.FieldSelector = fields.OneTermEqualSelector("metadata.name", operator.ResourceName).String() - } - - kubeInformersNamespaced := informers.NewSharedInformerFactoryWithOptions(kubeClient, resync, - informers.WithNamespace(operator.TargetNamespace), - informers.WithTweakListOptions(tweakListOptions), - ) - - exampleOperatorInformers := externalversions.NewSharedInformerFactoryWithOptions(exampleOperatorClient, resync, - externalversions.WithNamespace(operator.TargetNamespace), - externalversions.WithTweakListOptions(tweakListOptions), - ) - - exampleOperator := operator.NewExampleOperator( - exampleOperatorInformers.Exampleoperator().V1alpha1().ExampleOperators(), - kubeInformersNamespaced.Core().V1().Secrets(), - exampleOperatorClient.ExampleoperatorV1alpha1().ExampleOperators(operator.TargetNamespace), - kubeClient.CoreV1(), - ) - - kubeInformersNamespaced.Start(stopCh) - exampleOperatorInformers.Start(stopCh) - - go exampleOperator.Run(stopCh) - - <-stopCh - - return fmt.Errorf("stopped") -} diff --git a/pkg/generated/clientset/versioned/clientset.go b/pkg/generated/clientset/versioned/clientset.go index 54a7d42..b833cb6 100644 --- a/pkg/generated/clientset/versioned/clientset.go +++ b/pkg/generated/clientset/versioned/clientset.go @@ -3,7 +3,7 @@ package versioned import ( - exampleoperatorv1alpha1 "github.com/enj/example-operator/pkg/generated/clientset/versioned/typed/example/v1alpha1" + consolev1alpha1 "github.com/openshift/console-operator/pkg/generated/clientset/versioned/typed/console/v1alpha1" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -11,27 +11,27 @@ import ( type Interface interface { Discovery() discovery.DiscoveryInterface - ExampleoperatorV1alpha1() exampleoperatorv1alpha1.ExampleoperatorV1alpha1Interface + ConsoleV1alpha1() consolev1alpha1.ConsoleV1alpha1Interface // Deprecated: please explicitly pick a version if possible. - Exampleoperator() exampleoperatorv1alpha1.ExampleoperatorV1alpha1Interface + Console() consolev1alpha1.ConsoleV1alpha1Interface } // Clientset contains the clients for groups. Each group has exactly one // version included in a Clientset. type Clientset struct { *discovery.DiscoveryClient - exampleoperatorV1alpha1 *exampleoperatorv1alpha1.ExampleoperatorV1alpha1Client + consoleV1alpha1 *consolev1alpha1.ConsoleV1alpha1Client } -// ExampleoperatorV1alpha1 retrieves the ExampleoperatorV1alpha1Client -func (c *Clientset) ExampleoperatorV1alpha1() exampleoperatorv1alpha1.ExampleoperatorV1alpha1Interface { - return c.exampleoperatorV1alpha1 +// ConsoleV1alpha1 retrieves the ConsoleV1alpha1Client +func (c *Clientset) ConsoleV1alpha1() consolev1alpha1.ConsoleV1alpha1Interface { + return c.consoleV1alpha1 } -// Deprecated: Exampleoperator retrieves the default version of ExampleoperatorClient. +// Deprecated: Console retrieves the default version of ConsoleClient. // Please explicitly pick a version. -func (c *Clientset) Exampleoperator() exampleoperatorv1alpha1.ExampleoperatorV1alpha1Interface { - return c.exampleoperatorV1alpha1 +func (c *Clientset) Console() consolev1alpha1.ConsoleV1alpha1Interface { + return c.consoleV1alpha1 } // Discovery retrieves the DiscoveryClient @@ -50,7 +50,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { } var cs Clientset var err error - cs.exampleoperatorV1alpha1, err = exampleoperatorv1alpha1.NewForConfig(&configShallowCopy) + cs.consoleV1alpha1, err = consolev1alpha1.NewForConfig(&configShallowCopy) if err != nil { return nil, err } @@ -66,7 +66,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { // panics if there is an error in the config. func NewForConfigOrDie(c *rest.Config) *Clientset { var cs Clientset - cs.exampleoperatorV1alpha1 = exampleoperatorv1alpha1.NewForConfigOrDie(c) + cs.consoleV1alpha1 = consolev1alpha1.NewForConfigOrDie(c) cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) return &cs @@ -75,7 +75,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { // New creates a new Clientset for the given RESTClient. func New(c rest.Interface) *Clientset { var cs Clientset - cs.exampleoperatorV1alpha1 = exampleoperatorv1alpha1.New(c) + cs.consoleV1alpha1 = consolev1alpha1.New(c) cs.DiscoveryClient = discovery.NewDiscoveryClient(c) return &cs diff --git a/pkg/generated/clientset/versioned/fake/clientset_generated.go b/pkg/generated/clientset/versioned/fake/clientset_generated.go index 4191e2c..2f30ffc 100644 --- a/pkg/generated/clientset/versioned/fake/clientset_generated.go +++ b/pkg/generated/clientset/versioned/fake/clientset_generated.go @@ -3,9 +3,9 @@ package fake import ( - clientset "github.com/enj/example-operator/pkg/generated/clientset/versioned" - exampleoperatorv1alpha1 "github.com/enj/example-operator/pkg/generated/clientset/versioned/typed/example/v1alpha1" - fakeexampleoperatorv1alpha1 "github.com/enj/example-operator/pkg/generated/clientset/versioned/typed/example/v1alpha1/fake" + clientset "github.com/openshift/console-operator/pkg/generated/clientset/versioned" + consolev1alpha1 "github.com/openshift/console-operator/pkg/generated/clientset/versioned/typed/console/v1alpha1" + fakeconsolev1alpha1 "github.com/openshift/console-operator/pkg/generated/clientset/versioned/typed/console/v1alpha1/fake" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/discovery" @@ -55,12 +55,12 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface { var _ clientset.Interface = &Clientset{} -// ExampleoperatorV1alpha1 retrieves the ExampleoperatorV1alpha1Client -func (c *Clientset) ExampleoperatorV1alpha1() exampleoperatorv1alpha1.ExampleoperatorV1alpha1Interface { - return &fakeexampleoperatorv1alpha1.FakeExampleoperatorV1alpha1{Fake: &c.Fake} +// ConsoleV1alpha1 retrieves the ConsoleV1alpha1Client +func (c *Clientset) ConsoleV1alpha1() consolev1alpha1.ConsoleV1alpha1Interface { + return &fakeconsolev1alpha1.FakeConsoleV1alpha1{Fake: &c.Fake} } -// Exampleoperator retrieves the ExampleoperatorV1alpha1Client -func (c *Clientset) Exampleoperator() exampleoperatorv1alpha1.ExampleoperatorV1alpha1Interface { - return &fakeexampleoperatorv1alpha1.FakeExampleoperatorV1alpha1{Fake: &c.Fake} +// Console retrieves the ConsoleV1alpha1Client +func (c *Clientset) Console() consolev1alpha1.ConsoleV1alpha1Interface { + return &fakeconsolev1alpha1.FakeConsoleV1alpha1{Fake: &c.Fake} } diff --git a/pkg/generated/clientset/versioned/fake/register.go b/pkg/generated/clientset/versioned/fake/register.go index 23c48de..311819f 100644 --- a/pkg/generated/clientset/versioned/fake/register.go +++ b/pkg/generated/clientset/versioned/fake/register.go @@ -3,7 +3,7 @@ package fake import ( - exampleoperatorv1alpha1 "github.com/enj/example-operator/pkg/apis/example/v1alpha1" + consolev1alpha1 "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -34,5 +34,5 @@ func init() { // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types // correctly. func AddToScheme(scheme *runtime.Scheme) { - exampleoperatorv1alpha1.AddToScheme(scheme) + consolev1alpha1.AddToScheme(scheme) } diff --git a/pkg/generated/clientset/versioned/scheme/register.go b/pkg/generated/clientset/versioned/scheme/register.go index c8f435b..d33005b 100644 --- a/pkg/generated/clientset/versioned/scheme/register.go +++ b/pkg/generated/clientset/versioned/scheme/register.go @@ -3,7 +3,7 @@ package scheme import ( - exampleoperatorv1alpha1 "github.com/enj/example-operator/pkg/apis/example/v1alpha1" + consolev1alpha1 "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -34,5 +34,5 @@ func init() { // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types // correctly. func AddToScheme(scheme *runtime.Scheme) { - exampleoperatorv1alpha1.AddToScheme(scheme) + consolev1alpha1.AddToScheme(scheme) } diff --git a/pkg/generated/clientset/versioned/typed/console/v1alpha1/console.go b/pkg/generated/clientset/versioned/typed/console/v1alpha1/console.go new file mode 100644 index 0000000..e60e7de --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/console/v1alpha1/console.go @@ -0,0 +1,158 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" + scheme "github.com/openshift/console-operator/pkg/generated/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ConsolesGetter has a method to return a ConsoleInterface. +// A group's client should implement this interface. +type ConsolesGetter interface { + Consoles(namespace string) ConsoleInterface +} + +// ConsoleInterface has methods to work with Console resources. +type ConsoleInterface interface { + Create(*v1alpha1.Console) (*v1alpha1.Console, error) + Update(*v1alpha1.Console) (*v1alpha1.Console, error) + UpdateStatus(*v1alpha1.Console) (*v1alpha1.Console, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.Console, error) + List(opts v1.ListOptions) (*v1alpha1.ConsoleList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Console, err error) + ConsoleExpansion +} + +// consoles implements ConsoleInterface +type consoles struct { + client rest.Interface + ns string +} + +// newConsoles returns a Consoles +func newConsoles(c *ConsoleV1alpha1Client, namespace string) *consoles { + return &consoles{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the console, and returns the corresponding console object, and an error if there is any. +func (c *consoles) Get(name string, options v1.GetOptions) (result *v1alpha1.Console, err error) { + result = &v1alpha1.Console{} + err = c.client.Get(). + Namespace(c.ns). + Resource("consoles"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Consoles that match those selectors. +func (c *consoles) List(opts v1.ListOptions) (result *v1alpha1.ConsoleList, err error) { + result = &v1alpha1.ConsoleList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("consoles"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested consoles. +func (c *consoles) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("consoles"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a console and creates it. Returns the server's representation of the console, and an error, if there is any. +func (c *consoles) Create(console *v1alpha1.Console) (result *v1alpha1.Console, err error) { + result = &v1alpha1.Console{} + err = c.client.Post(). + Namespace(c.ns). + Resource("consoles"). + Body(console). + Do(). + Into(result) + return +} + +// Update takes the representation of a console and updates it. Returns the server's representation of the console, and an error, if there is any. +func (c *consoles) Update(console *v1alpha1.Console) (result *v1alpha1.Console, err error) { + result = &v1alpha1.Console{} + err = c.client.Put(). + Namespace(c.ns). + Resource("consoles"). + Name(console.Name). + Body(console). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *consoles) UpdateStatus(console *v1alpha1.Console) (result *v1alpha1.Console, err error) { + result = &v1alpha1.Console{} + err = c.client.Put(). + Namespace(c.ns). + Resource("consoles"). + Name(console.Name). + SubResource("status"). + Body(console). + Do(). + Into(result) + return +} + +// Delete takes name of the console and deletes it. Returns an error if one occurs. +func (c *consoles) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("consoles"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *consoles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("consoles"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched console. +func (c *consoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Console, err error) { + result = &v1alpha1.Console{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("consoles"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/generated/clientset/versioned/typed/console/v1alpha1/console_client.go b/pkg/generated/clientset/versioned/typed/console/v1alpha1/console_client.go new file mode 100644 index 0000000..c8276bb --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/console/v1alpha1/console_client.go @@ -0,0 +1,74 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" + "github.com/openshift/console-operator/pkg/generated/clientset/versioned/scheme" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + rest "k8s.io/client-go/rest" +) + +type ConsoleV1alpha1Interface interface { + RESTClient() rest.Interface + ConsolesGetter +} + +// ConsoleV1alpha1Client is used to interact with features provided by the console.openshift.io group. +type ConsoleV1alpha1Client struct { + restClient rest.Interface +} + +func (c *ConsoleV1alpha1Client) Consoles(namespace string) ConsoleInterface { + return newConsoles(c, namespace) +} + +// NewForConfig creates a new ConsoleV1alpha1Client for the given config. +func NewForConfig(c *rest.Config) (*ConsoleV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &ConsoleV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new ConsoleV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *ConsoleV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new ConsoleV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *ConsoleV1alpha1Client { + return &ConsoleV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *ConsoleV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/generated/clientset/versioned/typed/example/v1alpha1/doc.go b/pkg/generated/clientset/versioned/typed/console/v1alpha1/doc.go similarity index 100% rename from pkg/generated/clientset/versioned/typed/example/v1alpha1/doc.go rename to pkg/generated/clientset/versioned/typed/console/v1alpha1/doc.go diff --git a/pkg/generated/clientset/versioned/typed/example/v1alpha1/fake/doc.go b/pkg/generated/clientset/versioned/typed/console/v1alpha1/fake/doc.go similarity index 100% rename from pkg/generated/clientset/versioned/typed/example/v1alpha1/fake/doc.go rename to pkg/generated/clientset/versioned/typed/console/v1alpha1/fake/doc.go diff --git a/pkg/generated/clientset/versioned/typed/console/v1alpha1/fake/fake_console.go b/pkg/generated/clientset/versioned/typed/console/v1alpha1/fake/fake_console.go new file mode 100644 index 0000000..cfde9de --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/console/v1alpha1/fake/fake_console.go @@ -0,0 +1,124 @@ +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeConsoles implements ConsoleInterface +type FakeConsoles struct { + Fake *FakeConsoleV1alpha1 + ns string +} + +var consolesResource = schema.GroupVersionResource{Group: "console.openshift.io", Version: "v1alpha1", Resource: "consoles"} + +var consolesKind = schema.GroupVersionKind{Group: "console.openshift.io", Version: "v1alpha1", Kind: "Console"} + +// Get takes name of the console, and returns the corresponding console object, and an error if there is any. +func (c *FakeConsoles) Get(name string, options v1.GetOptions) (result *v1alpha1.Console, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(consolesResource, c.ns, name), &v1alpha1.Console{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Console), err +} + +// List takes label and field selectors, and returns the list of Consoles that match those selectors. +func (c *FakeConsoles) List(opts v1.ListOptions) (result *v1alpha1.ConsoleList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(consolesResource, consolesKind, c.ns, opts), &v1alpha1.ConsoleList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.ConsoleList{ListMeta: obj.(*v1alpha1.ConsoleList).ListMeta} + for _, item := range obj.(*v1alpha1.ConsoleList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested consoles. +func (c *FakeConsoles) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(consolesResource, c.ns, opts)) + +} + +// Create takes the representation of a console and creates it. Returns the server's representation of the console, and an error, if there is any. +func (c *FakeConsoles) Create(console *v1alpha1.Console) (result *v1alpha1.Console, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(consolesResource, c.ns, console), &v1alpha1.Console{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Console), err +} + +// Update takes the representation of a console and updates it. Returns the server's representation of the console, and an error, if there is any. +func (c *FakeConsoles) Update(console *v1alpha1.Console) (result *v1alpha1.Console, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(consolesResource, c.ns, console), &v1alpha1.Console{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Console), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeConsoles) UpdateStatus(console *v1alpha1.Console) (*v1alpha1.Console, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(consolesResource, "status", c.ns, console), &v1alpha1.Console{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Console), err +} + +// Delete takes name of the console and deletes it. Returns an error if one occurs. +func (c *FakeConsoles) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(consolesResource, c.ns, name), &v1alpha1.Console{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeConsoles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(consolesResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.ConsoleList{}) + return err +} + +// Patch applies the patch and returns the patched console. +func (c *FakeConsoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Console, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(consolesResource, c.ns, name, data, subresources...), &v1alpha1.Console{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Console), err +} diff --git a/pkg/generated/clientset/versioned/typed/console/v1alpha1/fake/fake_console_client.go b/pkg/generated/clientset/versioned/typed/console/v1alpha1/fake/fake_console_client.go new file mode 100644 index 0000000..7cc601a --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/console/v1alpha1/fake/fake_console_client.go @@ -0,0 +1,24 @@ +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/openshift/console-operator/pkg/generated/clientset/versioned/typed/console/v1alpha1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeConsoleV1alpha1 struct { + *testing.Fake +} + +func (c *FakeConsoleV1alpha1) Consoles(namespace string) v1alpha1.ConsoleInterface { + return &FakeConsoles{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeConsoleV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/generated/clientset/versioned/typed/example/v1alpha1/generated_expansion.go b/pkg/generated/clientset/versioned/typed/console/v1alpha1/generated_expansion.go similarity index 60% rename from pkg/generated/clientset/versioned/typed/example/v1alpha1/generated_expansion.go rename to pkg/generated/clientset/versioned/typed/console/v1alpha1/generated_expansion.go index 97fc64f..6ac17a0 100644 --- a/pkg/generated/clientset/versioned/typed/example/v1alpha1/generated_expansion.go +++ b/pkg/generated/clientset/versioned/typed/console/v1alpha1/generated_expansion.go @@ -2,4 +2,4 @@ package v1alpha1 -type ExampleOperatorExpansion interface{} +type ConsoleExpansion interface{} diff --git a/pkg/generated/clientset/versioned/typed/example/v1alpha1/example_client.go b/pkg/generated/clientset/versioned/typed/example/v1alpha1/example_client.go deleted file mode 100644 index 794e41b..0000000 --- a/pkg/generated/clientset/versioned/typed/example/v1alpha1/example_client.go +++ /dev/null @@ -1,74 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - v1alpha1 "github.com/enj/example-operator/pkg/apis/example/v1alpha1" - "github.com/enj/example-operator/pkg/generated/clientset/versioned/scheme" - serializer "k8s.io/apimachinery/pkg/runtime/serializer" - rest "k8s.io/client-go/rest" -) - -type ExampleoperatorV1alpha1Interface interface { - RESTClient() rest.Interface - ExampleOperatorsGetter -} - -// ExampleoperatorV1alpha1Client is used to interact with features provided by the exampleoperator.crd.monis.app group. -type ExampleoperatorV1alpha1Client struct { - restClient rest.Interface -} - -func (c *ExampleoperatorV1alpha1Client) ExampleOperators(namespace string) ExampleOperatorInterface { - return newExampleOperators(c, namespace) -} - -// NewForConfig creates a new ExampleoperatorV1alpha1Client for the given config. -func NewForConfig(c *rest.Config) (*ExampleoperatorV1alpha1Client, error) { - config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } - client, err := rest.RESTClientFor(&config) - if err != nil { - return nil, err - } - return &ExampleoperatorV1alpha1Client{client}, nil -} - -// NewForConfigOrDie creates a new ExampleoperatorV1alpha1Client for the given config and -// panics if there is an error in the config. -func NewForConfigOrDie(c *rest.Config) *ExampleoperatorV1alpha1Client { - client, err := NewForConfig(c) - if err != nil { - panic(err) - } - return client -} - -// New creates a new ExampleoperatorV1alpha1Client for the given RESTClient. -func New(c rest.Interface) *ExampleoperatorV1alpha1Client { - return &ExampleoperatorV1alpha1Client{c} -} - -func setConfigDefaults(config *rest.Config) error { - gv := v1alpha1.SchemeGroupVersion - config.GroupVersion = &gv - config.APIPath = "/apis" - config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} - - if config.UserAgent == "" { - config.UserAgent = rest.DefaultKubernetesUserAgent() - } - - return nil -} - -// RESTClient returns a RESTClient that is used to communicate -// with API server by this client implementation. -func (c *ExampleoperatorV1alpha1Client) RESTClient() rest.Interface { - if c == nil { - return nil - } - return c.restClient -} diff --git a/pkg/generated/clientset/versioned/typed/example/v1alpha1/exampleoperator.go b/pkg/generated/clientset/versioned/typed/example/v1alpha1/exampleoperator.go deleted file mode 100644 index 61be1ab..0000000 --- a/pkg/generated/clientset/versioned/typed/example/v1alpha1/exampleoperator.go +++ /dev/null @@ -1,158 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - v1alpha1 "github.com/enj/example-operator/pkg/apis/example/v1alpha1" - scheme "github.com/enj/example-operator/pkg/generated/clientset/versioned/scheme" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// ExampleOperatorsGetter has a method to return a ExampleOperatorInterface. -// A group's client should implement this interface. -type ExampleOperatorsGetter interface { - ExampleOperators(namespace string) ExampleOperatorInterface -} - -// ExampleOperatorInterface has methods to work with ExampleOperator resources. -type ExampleOperatorInterface interface { - Create(*v1alpha1.ExampleOperator) (*v1alpha1.ExampleOperator, error) - Update(*v1alpha1.ExampleOperator) (*v1alpha1.ExampleOperator, error) - UpdateStatus(*v1alpha1.ExampleOperator) (*v1alpha1.ExampleOperator, error) - Delete(name string, options *v1.DeleteOptions) error - DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error - Get(name string, options v1.GetOptions) (*v1alpha1.ExampleOperator, error) - List(opts v1.ListOptions) (*v1alpha1.ExampleOperatorList, error) - Watch(opts v1.ListOptions) (watch.Interface, error) - Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ExampleOperator, err error) - ExampleOperatorExpansion -} - -// exampleOperators implements ExampleOperatorInterface -type exampleOperators struct { - client rest.Interface - ns string -} - -// newExampleOperators returns a ExampleOperators -func newExampleOperators(c *ExampleoperatorV1alpha1Client, namespace string) *exampleOperators { - return &exampleOperators{ - client: c.RESTClient(), - ns: namespace, - } -} - -// Get takes name of the exampleOperator, and returns the corresponding exampleOperator object, and an error if there is any. -func (c *exampleOperators) Get(name string, options v1.GetOptions) (result *v1alpha1.ExampleOperator, err error) { - result = &v1alpha1.ExampleOperator{} - err = c.client.Get(). - Namespace(c.ns). - Resource("exampleoperators"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of ExampleOperators that match those selectors. -func (c *exampleOperators) List(opts v1.ListOptions) (result *v1alpha1.ExampleOperatorList, err error) { - result = &v1alpha1.ExampleOperatorList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("exampleoperators"). - VersionedParams(&opts, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested exampleOperators. -func (c *exampleOperators) Watch(opts v1.ListOptions) (watch.Interface, error) { - opts.Watch = true - return c.client.Get(). - Namespace(c.ns). - Resource("exampleoperators"). - VersionedParams(&opts, scheme.ParameterCodec). - Watch() -} - -// Create takes the representation of a exampleOperator and creates it. Returns the server's representation of the exampleOperator, and an error, if there is any. -func (c *exampleOperators) Create(exampleOperator *v1alpha1.ExampleOperator) (result *v1alpha1.ExampleOperator, err error) { - result = &v1alpha1.ExampleOperator{} - err = c.client.Post(). - Namespace(c.ns). - Resource("exampleoperators"). - Body(exampleOperator). - Do(). - Into(result) - return -} - -// Update takes the representation of a exampleOperator and updates it. Returns the server's representation of the exampleOperator, and an error, if there is any. -func (c *exampleOperators) Update(exampleOperator *v1alpha1.ExampleOperator) (result *v1alpha1.ExampleOperator, err error) { - result = &v1alpha1.ExampleOperator{} - err = c.client.Put(). - Namespace(c.ns). - Resource("exampleoperators"). - Name(exampleOperator.Name). - Body(exampleOperator). - Do(). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). - -func (c *exampleOperators) UpdateStatus(exampleOperator *v1alpha1.ExampleOperator) (result *v1alpha1.ExampleOperator, err error) { - result = &v1alpha1.ExampleOperator{} - err = c.client.Put(). - Namespace(c.ns). - Resource("exampleoperators"). - Name(exampleOperator.Name). - SubResource("status"). - Body(exampleOperator). - Do(). - Into(result) - return -} - -// Delete takes name of the exampleOperator and deletes it. Returns an error if one occurs. -func (c *exampleOperators) Delete(name string, options *v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("exampleoperators"). - Name(name). - Body(options). - Do(). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *exampleOperators) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("exampleoperators"). - VersionedParams(&listOptions, scheme.ParameterCodec). - Body(options). - Do(). - Error() -} - -// Patch applies the patch and returns the patched exampleOperator. -func (c *exampleOperators) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ExampleOperator, err error) { - result = &v1alpha1.ExampleOperator{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("exampleoperators"). - SubResource(subresources...). - Name(name). - Body(data). - Do(). - Into(result) - return -} diff --git a/pkg/generated/clientset/versioned/typed/example/v1alpha1/fake/fake_example_client.go b/pkg/generated/clientset/versioned/typed/example/v1alpha1/fake/fake_example_client.go deleted file mode 100644 index 3bf4045..0000000 --- a/pkg/generated/clientset/versioned/typed/example/v1alpha1/fake/fake_example_client.go +++ /dev/null @@ -1,24 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - v1alpha1 "github.com/enj/example-operator/pkg/generated/clientset/versioned/typed/example/v1alpha1" - rest "k8s.io/client-go/rest" - testing "k8s.io/client-go/testing" -) - -type FakeExampleoperatorV1alpha1 struct { - *testing.Fake -} - -func (c *FakeExampleoperatorV1alpha1) ExampleOperators(namespace string) v1alpha1.ExampleOperatorInterface { - return &FakeExampleOperators{c, namespace} -} - -// RESTClient returns a RESTClient that is used to communicate -// with API server by this client implementation. -func (c *FakeExampleoperatorV1alpha1) RESTClient() rest.Interface { - var ret *rest.RESTClient - return ret -} diff --git a/pkg/generated/clientset/versioned/typed/example/v1alpha1/fake/fake_exampleoperator.go b/pkg/generated/clientset/versioned/typed/example/v1alpha1/fake/fake_exampleoperator.go deleted file mode 100644 index 797240c..0000000 --- a/pkg/generated/clientset/versioned/typed/example/v1alpha1/fake/fake_exampleoperator.go +++ /dev/null @@ -1,124 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - v1alpha1 "github.com/enj/example-operator/pkg/apis/example/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - schema "k8s.io/apimachinery/pkg/runtime/schema" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeExampleOperators implements ExampleOperatorInterface -type FakeExampleOperators struct { - Fake *FakeExampleoperatorV1alpha1 - ns string -} - -var exampleoperatorsResource = schema.GroupVersionResource{Group: "exampleoperator.crd.monis.app", Version: "v1alpha1", Resource: "exampleoperators"} - -var exampleoperatorsKind = schema.GroupVersionKind{Group: "exampleoperator.crd.monis.app", Version: "v1alpha1", Kind: "ExampleOperator"} - -// Get takes name of the exampleOperator, and returns the corresponding exampleOperator object, and an error if there is any. -func (c *FakeExampleOperators) Get(name string, options v1.GetOptions) (result *v1alpha1.ExampleOperator, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(exampleoperatorsResource, c.ns, name), &v1alpha1.ExampleOperator{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExampleOperator), err -} - -// List takes label and field selectors, and returns the list of ExampleOperators that match those selectors. -func (c *FakeExampleOperators) List(opts v1.ListOptions) (result *v1alpha1.ExampleOperatorList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(exampleoperatorsResource, exampleoperatorsKind, c.ns, opts), &v1alpha1.ExampleOperatorList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha1.ExampleOperatorList{ListMeta: obj.(*v1alpha1.ExampleOperatorList).ListMeta} - for _, item := range obj.(*v1alpha1.ExampleOperatorList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested exampleOperators. -func (c *FakeExampleOperators) Watch(opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(exampleoperatorsResource, c.ns, opts)) - -} - -// Create takes the representation of a exampleOperator and creates it. Returns the server's representation of the exampleOperator, and an error, if there is any. -func (c *FakeExampleOperators) Create(exampleOperator *v1alpha1.ExampleOperator) (result *v1alpha1.ExampleOperator, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(exampleoperatorsResource, c.ns, exampleOperator), &v1alpha1.ExampleOperator{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExampleOperator), err -} - -// Update takes the representation of a exampleOperator and updates it. Returns the server's representation of the exampleOperator, and an error, if there is any. -func (c *FakeExampleOperators) Update(exampleOperator *v1alpha1.ExampleOperator) (result *v1alpha1.ExampleOperator, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(exampleoperatorsResource, c.ns, exampleOperator), &v1alpha1.ExampleOperator{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExampleOperator), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeExampleOperators) UpdateStatus(exampleOperator *v1alpha1.ExampleOperator) (*v1alpha1.ExampleOperator, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(exampleoperatorsResource, "status", c.ns, exampleOperator), &v1alpha1.ExampleOperator{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExampleOperator), err -} - -// Delete takes name of the exampleOperator and deletes it. Returns an error if one occurs. -func (c *FakeExampleOperators) Delete(name string, options *v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteAction(exampleoperatorsResource, c.ns, name), &v1alpha1.ExampleOperator{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeExampleOperators) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(exampleoperatorsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &v1alpha1.ExampleOperatorList{}) - return err -} - -// Patch applies the patch and returns the patched exampleOperator. -func (c *FakeExampleOperators) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ExampleOperator, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(exampleoperatorsResource, c.ns, name, data, subresources...), &v1alpha1.ExampleOperator{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExampleOperator), err -} diff --git a/pkg/generated/informers/externalversions/example/interface.go b/pkg/generated/informers/externalversions/console/interface.go similarity index 77% rename from pkg/generated/informers/externalversions/example/interface.go rename to pkg/generated/informers/externalversions/console/interface.go index 44207d6..40d7627 100644 --- a/pkg/generated/informers/externalversions/example/interface.go +++ b/pkg/generated/informers/externalversions/console/interface.go @@ -1,10 +1,10 @@ // Code generated by informer-gen. DO NOT EDIT. -package exampleoperator +package console import ( - v1alpha1 "github.com/enj/example-operator/pkg/generated/informers/externalversions/example/v1alpha1" - internalinterfaces "github.com/enj/example-operator/pkg/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/openshift/console-operator/pkg/generated/informers/externalversions/console/v1alpha1" + internalinterfaces "github.com/openshift/console-operator/pkg/generated/informers/externalversions/internalinterfaces" ) // Interface provides access to each of this group's versions. diff --git a/pkg/generated/informers/externalversions/console/v1alpha1/console.go b/pkg/generated/informers/externalversions/console/v1alpha1/console.go new file mode 100644 index 0000000..afac47f --- /dev/null +++ b/pkg/generated/informers/externalversions/console/v1alpha1/console.go @@ -0,0 +1,73 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + console_v1alpha1 "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" + versioned "github.com/openshift/console-operator/pkg/generated/clientset/versioned" + internalinterfaces "github.com/openshift/console-operator/pkg/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/openshift/console-operator/pkg/generated/listers/console/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ConsoleInformer provides access to a shared informer and lister for +// Consoles. +type ConsoleInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ConsoleLister +} + +type consoleInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewConsoleInformer constructs a new informer for Console type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewConsoleInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredConsoleInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredConsoleInformer constructs a new informer for Console type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredConsoleInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ConsoleV1alpha1().Consoles(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ConsoleV1alpha1().Consoles(namespace).Watch(options) + }, + }, + &console_v1alpha1.Console{}, + resyncPeriod, + indexers, + ) +} + +func (f *consoleInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredConsoleInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *consoleInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&console_v1alpha1.Console{}, f.defaultInformer) +} + +func (f *consoleInformer) Lister() v1alpha1.ConsoleLister { + return v1alpha1.NewConsoleLister(f.Informer().GetIndexer()) +} diff --git a/pkg/generated/informers/externalversions/example/v1alpha1/interface.go b/pkg/generated/informers/externalversions/console/v1alpha1/interface.go similarity index 57% rename from pkg/generated/informers/externalversions/example/v1alpha1/interface.go rename to pkg/generated/informers/externalversions/console/v1alpha1/interface.go index ecb07b5..c663280 100644 --- a/pkg/generated/informers/externalversions/example/v1alpha1/interface.go +++ b/pkg/generated/informers/externalversions/console/v1alpha1/interface.go @@ -3,13 +3,13 @@ package v1alpha1 import ( - internalinterfaces "github.com/enj/example-operator/pkg/generated/informers/externalversions/internalinterfaces" + internalinterfaces "github.com/openshift/console-operator/pkg/generated/informers/externalversions/internalinterfaces" ) // Interface provides access to all the informers in this group version. type Interface interface { - // ExampleOperators returns a ExampleOperatorInformer. - ExampleOperators() ExampleOperatorInformer + // Consoles returns a ConsoleInformer. + Consoles() ConsoleInformer } type version struct { @@ -23,7 +23,7 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } -// ExampleOperators returns a ExampleOperatorInformer. -func (v *version) ExampleOperators() ExampleOperatorInformer { - return &exampleOperatorInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +// Consoles returns a ConsoleInformer. +func (v *version) Consoles() ConsoleInformer { + return &consoleInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } diff --git a/pkg/generated/informers/externalversions/example/v1alpha1/exampleoperator.go b/pkg/generated/informers/externalversions/example/v1alpha1/exampleoperator.go deleted file mode 100644 index 7aa66c6..0000000 --- a/pkg/generated/informers/externalversions/example/v1alpha1/exampleoperator.go +++ /dev/null @@ -1,73 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - time "time" - - example_v1alpha1 "github.com/enj/example-operator/pkg/apis/example/v1alpha1" - versioned "github.com/enj/example-operator/pkg/generated/clientset/versioned" - internalinterfaces "github.com/enj/example-operator/pkg/generated/informers/externalversions/internalinterfaces" - v1alpha1 "github.com/enj/example-operator/pkg/generated/listers/example/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - watch "k8s.io/apimachinery/pkg/watch" - cache "k8s.io/client-go/tools/cache" -) - -// ExampleOperatorInformer provides access to a shared informer and lister for -// ExampleOperators. -type ExampleOperatorInformer interface { - Informer() cache.SharedIndexInformer - Lister() v1alpha1.ExampleOperatorLister -} - -type exampleOperatorInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string -} - -// NewExampleOperatorInformer constructs a new informer for ExampleOperator type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewExampleOperatorInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredExampleOperatorInformer(client, namespace, resyncPeriod, indexers, nil) -} - -// NewFilteredExampleOperatorInformer constructs a new informer for ExampleOperator type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewFilteredExampleOperatorInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.ExampleoperatorV1alpha1().ExampleOperators(namespace).List(options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.ExampleoperatorV1alpha1().ExampleOperators(namespace).Watch(options) - }, - }, - &example_v1alpha1.ExampleOperator{}, - resyncPeriod, - indexers, - ) -} - -func (f *exampleOperatorInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredExampleOperatorInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) -} - -func (f *exampleOperatorInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&example_v1alpha1.ExampleOperator{}, f.defaultInformer) -} - -func (f *exampleOperatorInformer) Lister() v1alpha1.ExampleOperatorLister { - return v1alpha1.NewExampleOperatorLister(f.Informer().GetIndexer()) -} diff --git a/pkg/generated/informers/externalversions/factory.go b/pkg/generated/informers/externalversions/factory.go index 905347e..19f2774 100644 --- a/pkg/generated/informers/externalversions/factory.go +++ b/pkg/generated/informers/externalversions/factory.go @@ -7,9 +7,9 @@ import ( sync "sync" time "time" - versioned "github.com/enj/example-operator/pkg/generated/clientset/versioned" - example "github.com/enj/example-operator/pkg/generated/informers/externalversions/example" - internalinterfaces "github.com/enj/example-operator/pkg/generated/informers/externalversions/internalinterfaces" + versioned "github.com/openshift/console-operator/pkg/generated/clientset/versioned" + console "github.com/openshift/console-operator/pkg/generated/informers/externalversions/console" + internalinterfaces "github.com/openshift/console-operator/pkg/generated/informers/externalversions/internalinterfaces" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -156,9 +156,9 @@ type SharedInformerFactory interface { ForResource(resource schema.GroupVersionResource) (GenericInformer, error) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool - Exampleoperator() example.Interface + Console() console.Interface } -func (f *sharedInformerFactory) Exampleoperator() example.Interface { - return example.New(f, f.namespace, f.tweakListOptions) +func (f *sharedInformerFactory) Console() console.Interface { + return console.New(f, f.namespace, f.tweakListOptions) } diff --git a/pkg/generated/informers/externalversions/generic.go b/pkg/generated/informers/externalversions/generic.go index 649e87f..fad1a03 100644 --- a/pkg/generated/informers/externalversions/generic.go +++ b/pkg/generated/informers/externalversions/generic.go @@ -5,7 +5,7 @@ package externalversions import ( "fmt" - v1alpha1 "github.com/enj/example-operator/pkg/apis/example/v1alpha1" + v1alpha1 "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" ) @@ -36,9 +36,9 @@ func (f *genericInformer) Lister() cache.GenericLister { // TODO extend this to unknown resources with a client pool func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { - // Group=exampleoperator.crd.monis.app, Version=v1alpha1 - case v1alpha1.SchemeGroupVersion.WithResource("exampleoperators"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Exampleoperator().V1alpha1().ExampleOperators().Informer()}, nil + // Group=console.openshift.io, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("consoles"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Console().V1alpha1().Consoles().Informer()}, nil } diff --git a/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go index 3ea1ad6..8585515 100644 --- a/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -5,7 +5,7 @@ package internalinterfaces import ( time "time" - versioned "github.com/enj/example-operator/pkg/generated/clientset/versioned" + versioned "github.com/openshift/console-operator/pkg/generated/clientset/versioned" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" cache "k8s.io/client-go/tools/cache" diff --git a/pkg/generated/listers/console/v1alpha1/console.go b/pkg/generated/listers/console/v1alpha1/console.go new file mode 100644 index 0000000..b82b1f8 --- /dev/null +++ b/pkg/generated/listers/console/v1alpha1/console.go @@ -0,0 +1,78 @@ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ConsoleLister helps list Consoles. +type ConsoleLister interface { + // List lists all Consoles in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.Console, err error) + // Consoles returns an object that can list and get Consoles. + Consoles(namespace string) ConsoleNamespaceLister + ConsoleListerExpansion +} + +// consoleLister implements the ConsoleLister interface. +type consoleLister struct { + indexer cache.Indexer +} + +// NewConsoleLister returns a new ConsoleLister. +func NewConsoleLister(indexer cache.Indexer) ConsoleLister { + return &consoleLister{indexer: indexer} +} + +// List lists all Consoles in the indexer. +func (s *consoleLister) List(selector labels.Selector) (ret []*v1alpha1.Console, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Console)) + }) + return ret, err +} + +// Consoles returns an object that can list and get Consoles. +func (s *consoleLister) Consoles(namespace string) ConsoleNamespaceLister { + return consoleNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ConsoleNamespaceLister helps list and get Consoles. +type ConsoleNamespaceLister interface { + // List lists all Consoles in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1alpha1.Console, err error) + // Get retrieves the Console from the indexer for a given namespace and name. + Get(name string) (*v1alpha1.Console, error) + ConsoleNamespaceListerExpansion +} + +// consoleNamespaceLister implements the ConsoleNamespaceLister +// interface. +type consoleNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Consoles in the indexer for a given namespace. +func (s consoleNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.Console, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Console)) + }) + return ret, err +} + +// Get retrieves the Console from the indexer for a given namespace and name. +func (s consoleNamespaceLister) Get(name string) (*v1alpha1.Console, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("console"), name) + } + return obj.(*v1alpha1.Console), nil +} diff --git a/pkg/generated/listers/console/v1alpha1/expansion_generated.go b/pkg/generated/listers/console/v1alpha1/expansion_generated.go new file mode 100644 index 0000000..01fda3c --- /dev/null +++ b/pkg/generated/listers/console/v1alpha1/expansion_generated.go @@ -0,0 +1,11 @@ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// ConsoleListerExpansion allows custom methods to be added to +// ConsoleLister. +type ConsoleListerExpansion interface{} + +// ConsoleNamespaceListerExpansion allows custom methods to be added to +// ConsoleNamespaceLister. +type ConsoleNamespaceListerExpansion interface{} diff --git a/pkg/generated/listers/example/v1alpha1/exampleoperator.go b/pkg/generated/listers/example/v1alpha1/exampleoperator.go deleted file mode 100644 index be471f4..0000000 --- a/pkg/generated/listers/example/v1alpha1/exampleoperator.go +++ /dev/null @@ -1,78 +0,0 @@ -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - v1alpha1 "github.com/enj/example-operator/pkg/apis/example/v1alpha1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// ExampleOperatorLister helps list ExampleOperators. -type ExampleOperatorLister interface { - // List lists all ExampleOperators in the indexer. - List(selector labels.Selector) (ret []*v1alpha1.ExampleOperator, err error) - // ExampleOperators returns an object that can list and get ExampleOperators. - ExampleOperators(namespace string) ExampleOperatorNamespaceLister - ExampleOperatorListerExpansion -} - -// exampleOperatorLister implements the ExampleOperatorLister interface. -type exampleOperatorLister struct { - indexer cache.Indexer -} - -// NewExampleOperatorLister returns a new ExampleOperatorLister. -func NewExampleOperatorLister(indexer cache.Indexer) ExampleOperatorLister { - return &exampleOperatorLister{indexer: indexer} -} - -// List lists all ExampleOperators in the indexer. -func (s *exampleOperatorLister) List(selector labels.Selector) (ret []*v1alpha1.ExampleOperator, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.ExampleOperator)) - }) - return ret, err -} - -// ExampleOperators returns an object that can list and get ExampleOperators. -func (s *exampleOperatorLister) ExampleOperators(namespace string) ExampleOperatorNamespaceLister { - return exampleOperatorNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// ExampleOperatorNamespaceLister helps list and get ExampleOperators. -type ExampleOperatorNamespaceLister interface { - // List lists all ExampleOperators in the indexer for a given namespace. - List(selector labels.Selector) (ret []*v1alpha1.ExampleOperator, err error) - // Get retrieves the ExampleOperator from the indexer for a given namespace and name. - Get(name string) (*v1alpha1.ExampleOperator, error) - ExampleOperatorNamespaceListerExpansion -} - -// exampleOperatorNamespaceLister implements the ExampleOperatorNamespaceLister -// interface. -type exampleOperatorNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all ExampleOperators in the indexer for a given namespace. -func (s exampleOperatorNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ExampleOperator, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.ExampleOperator)) - }) - return ret, err -} - -// Get retrieves the ExampleOperator from the indexer for a given namespace and name. -func (s exampleOperatorNamespaceLister) Get(name string) (*v1alpha1.ExampleOperator, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("exampleoperator"), name) - } - return obj.(*v1alpha1.ExampleOperator), nil -} diff --git a/pkg/generated/listers/example/v1alpha1/expansion_generated.go b/pkg/generated/listers/example/v1alpha1/expansion_generated.go deleted file mode 100644 index 518afa8..0000000 --- a/pkg/generated/listers/example/v1alpha1/expansion_generated.go +++ /dev/null @@ -1,11 +0,0 @@ -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha1 - -// ExampleOperatorListerExpansion allows custom methods to be added to -// ExampleOperatorLister. -type ExampleOperatorListerExpansion interface{} - -// ExampleOperatorNamespaceListerExpansion allows custom methods to be added to -// ExampleOperatorNamespaceLister. -type ExampleOperatorNamespaceListerExpansion interface{} From 4053c8f458882f0fdf54490ddbd2046ddf98edba Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Wed, 7 Nov 2018 14:23:22 -0500 Subject: [PATCH 02/24] Update manifests to match existing console-operator manifests --- examples/cr.yaml | 20 +++++++ examples/crd-clusteroperator.yaml | 20 +++++++ install/config.yaml | 4 -- install/cr.yaml | 36 ----------- install/install-rbac.yaml | 16 ----- install/install.yaml | 96 ------------------------------ manifests/00-oauth.yaml | 6 ++ manifests/01-namespace.yaml | 4 ++ manifests/02-rbac-role.yaml | 70 ++++++++++++++++++++++ manifests/03-rbac-rolebinding.yaml | 25 ++++++++ manifests/04-sa.yaml | 5 ++ manifests/05-operator.yaml | 36 +++++++++++ manifests/clusterrole.yaml | 28 --------- manifests/clusterrolebinding.yaml | 11 ---- manifests/cm.yaml | 7 --- manifests/defaultconfig.yaml | 5 -- manifests/deployment.yaml | 53 ----------------- manifests/image-references | 13 ++++ manifests/ns.yaml | 6 -- manifests/sa.yaml | 5 -- manifests/signing-secret.yaml | 9 --- manifests/svc.yaml | 16 ----- 22 files changed, 199 insertions(+), 292 deletions(-) create mode 100644 examples/cr.yaml create mode 100644 examples/crd-clusteroperator.yaml delete mode 100644 install/config.yaml delete mode 100644 install/cr.yaml delete mode 100644 install/install-rbac.yaml delete mode 100644 install/install.yaml create mode 100644 manifests/00-oauth.yaml create mode 100644 manifests/01-namespace.yaml create mode 100644 manifests/02-rbac-role.yaml create mode 100644 manifests/03-rbac-rolebinding.yaml create mode 100644 manifests/04-sa.yaml create mode 100644 manifests/05-operator.yaml delete mode 100644 manifests/clusterrole.yaml delete mode 100644 manifests/clusterrolebinding.yaml delete mode 100644 manifests/cm.yaml delete mode 100644 manifests/defaultconfig.yaml delete mode 100644 manifests/deployment.yaml create mode 100644 manifests/image-references delete mode 100644 manifests/ns.yaml delete mode 100644 manifests/sa.yaml delete mode 100644 manifests/signing-secret.yaml delete mode 100644 manifests/svc.yaml diff --git a/examples/cr.yaml b/examples/cr.yaml new file mode 100644 index 0000000..b8ed6fe --- /dev/null +++ b/examples/cr.yaml @@ -0,0 +1,20 @@ +# The console-operator will create a console automatically on startup if one does not exist. +# This file is an example of a console resource. +# You may edit this file and `oc apply -f cr.yaml` to make changes to the console. +apiVersion: "console.openshift.io/v1alpha1" +kind: "Console" +metadata: + # Do not change the name, the operator explicitly requires this name to match as the console is a singleton. + name: openshift-console + namespace: openshift-console +spec: + # openshift/api/operator/v1alpha1/types.go + # managementState indicates whether the operator is: + # - Managed indicates the operator fully manages the state of the console and its sub-resources + # - Unmanaged indicates that the operator should idle and ignore the console and its sub-resources + # - Removed indicates that the operator should delete all of the sub-resources of the console + managementState: Managed + # there should be only one console at this time + count: 1 + logging: + level: 0 diff --git a/examples/crd-clusteroperator.yaml b/examples/crd-clusteroperator.yaml new file mode 100644 index 0000000..7490649 --- /dev/null +++ b/examples/crd-clusteroperator.yaml @@ -0,0 +1,20 @@ +# this CRD is for the ClusterOperator resource that is used to +# convey the operator status. It does NOT need to be a part of +# the manifests payload as it should be created early on, however, +# for local development, it may be necessary to `oc create -f` +# this file. +# to view the object: +# oc get clusteroperators openshift-console +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: clusteroperators.operatorstatus.openshift.io +spec: + group: operatorstatus.openshift.io + names: + kind: ClusterOperator + listKind: ClusterOperatorList + plural: clusteroperators + singular: clusteroperators + scope: Cluster + version: v1 diff --git a/install/config.yaml b/install/config.yaml deleted file mode 100644 index 3cc6062..0000000 --- a/install/config.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: operator.openshift.io/v1alpha1 -kind: GenericOperatorConfig -leaderElection: - namespace: console-operator diff --git a/install/cr.yaml b/install/cr.yaml deleted file mode 100644 index 0b83879..0000000 --- a/install/cr.yaml +++ /dev/null @@ -1,36 +0,0 @@ -apiVersion: console.openshift.io/v1alpha1 -kind: Console -metadata: - name: console-operator-resource - namespace: openshift-console -spec: - managementState: Managed - version: 3.10.0 - value: this-is-actually-a-key-with-a-random-bytes-value - count: 1 - logging: - level: 0 - -# this is the old one. -# remove soon. -# -## The console-operator will create a console automatically on startup if one does not exist. -## This file is an example of a console resource. -## You may edit this file and `oc apply -f cr.yaml` to make changes to the console. -#apiVersion: "console.openshift.io/v1alpha1" -#kind: "Console" -#metadata: -# # Do not change the name, the operator explicitly requires this name to match as the console is a singleton. -# name: openshift-console -# namespace: openshift-console -#spec: -# # openshift/api/operator/v1alpha1/types.go -# # managementState indicates whether the operator is: -# # - Managed indicates the operator fully manages the state of the console and its sub-resources -# # - Unmanaged indicates that the operator should idle and ignore the console and its sub-resources -# # - Removed indicates that the operator should delete all of the sub-resources of the console -# managementState: Managed -# # there should be only one console at this time -# count: 1 -# logging: -# level: 0 diff --git a/install/install-rbac.yaml b/install/install-rbac.yaml deleted file mode 100644 index 2ae48b8..0000000 --- a/install/install-rbac.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: List -items: - -# When we have an orchestrating operator, it will do this -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRoleBinding - metadata: - name: system:openshift:operator:service-cert-signer - roleRef: - kind: ClusterRole - name: cluster-admin - subjects: - - kind: ServiceAccount - namespace: openshift-core-operators - name: openshift-service-ca-operator diff --git a/install/install.yaml b/install/install.yaml deleted file mode 100644 index c26d21d..0000000 --- a/install/install.yaml +++ /dev/null @@ -1,96 +0,0 @@ -apiVersion: v1 -kind: List -items: - -- apiVersion: v1 - kind: Namespace - metadata: - labels: - openshift.io/run-level: "1" - name: openshift-core-operators - -- apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - name: servicecertsigneroperatorconfigs.servicecertsigner.config.openshift.io - spec: - scope: Cluster - group: servicecertsigner.config.openshift.io - version: v1alpha1 - names: - kind: ServiceCertSignerOperatorConfig - plural: servicecertsigneroperatorconfigs - singular: servicecertsigneroperatorconfig - subresources: - status: {} - -- apiVersion: v1 - kind: ConfigMap - metadata: - namespace: openshift-core-operators - name: openshift-service-ca-operator-config - data: - operator-config.yaml: | - apiVersion: operator.openshift.io/v1alpha1 - kind: GenericOperatorConfig - -- apiVersion: apps/v1 - kind: Deployment - metadata: - namespace: openshift-core-operators - name: openshift-service-ca-operator - labels: - app: openshift-service-ca-operator - spec: - replicas: 1 - selector: - matchLabels: - app: openshift-service-ca-operator - template: - metadata: - name: openshift-service-ca-operator - labels: - app: openshift-service-ca-operator - spec: - serviceAccountName: openshift-service-ca-operator - containers: - - name: operator - image: openshift/origin-service-ca:latest - imagePullPolicy: IfNotPresent - command: ["service-ca", "operator"] - args: - - "--config=/var/run/configmaps/config/operator-config.yaml" - - "-v=4" - volumeMounts: - - mountPath: /var/run/configmaps/config - name: config - volumes: - - name: serving-cert - secret: - defaultMode: 400 - secretName: openshift-service-ca-operator-serving-cert - optional: true - - name: config - configMap: - defaultMode: 440 - name: openshift-service-ca-operator-config - -- apiVersion: v1 - kind: ServiceAccount - metadata: - namespace: openshift-core-operators - name: openshift-service-ca-operator - labels: - app: openshift-service-ca-operator - -- apiVersion: servicecertsigner.config.openshift.io/v1alpha1 - kind: ServiceCertSignerOperatorConfig - metadata: - name: instance - spec: - managementState: Managed - imagePullSpec: openshift/origin-service-ca:latest - version: 3.10.0 - logging: - level: 4 - replicas: 1 diff --git a/manifests/00-oauth.yaml b/manifests/00-oauth.yaml new file mode 100644 index 0000000..fc9c736 --- /dev/null +++ b/manifests/00-oauth.yaml @@ -0,0 +1,6 @@ +apiVersion: oauth.openshift.io/v1 +kind: OAuthClient +metadata: + name: openshift-console +grantMethod: auto +respondWithChallenges: false diff --git a/manifests/01-namespace.yaml b/manifests/01-namespace.yaml new file mode 100644 index 0000000..dd8e2d2 --- /dev/null +++ b/manifests/01-namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: openshift-console diff --git a/manifests/02-rbac-role.yaml b/manifests/02-rbac-role.yaml new file mode 100644 index 0000000..4402161 --- /dev/null +++ b/manifests/02-rbac-role.yaml @@ -0,0 +1,70 @@ +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: console-operator + namespace: openshift-console +rules: +# TODO: delete is needed for ownerRefs on older clusters +# should remove in the future. +- apiGroups: + - console.openshift.io + resources: + - consoles + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - "" + resources: + - services + - events + - configmaps + - secrets + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - apps + resources: + - deployments + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - get + - list + - watch + - create + - update + - delete +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: console-operator +rules: +- apiGroups: + - oauth.openshift.io + resources: + - oauthclients + verbs: + - get + - update + resourceNames: + - openshift-console diff --git a/manifests/03-rbac-rolebinding.yaml b/manifests/03-rbac-rolebinding.yaml new file mode 100644 index 0000000..4cffffc --- /dev/null +++ b/manifests/03-rbac-rolebinding.yaml @@ -0,0 +1,25 @@ +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: console-operator + namespace: openshift-console +roleRef: + kind: Role + name: console-operator + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: ServiceAccount + name: console-operator +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: console-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: console-operator +subjects: +- kind: ServiceAccount + name: console-operator + namespace: openshift-console diff --git a/manifests/04-sa.yaml b/manifests/04-sa.yaml new file mode 100644 index 0000000..55669f6 --- /dev/null +++ b/manifests/04-sa.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: console-operator + namespace: openshift-console diff --git a/manifests/05-operator.yaml b/manifests/05-operator.yaml new file mode 100644 index 0000000..2e5d280 --- /dev/null +++ b/manifests/05-operator.yaml @@ -0,0 +1,36 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: console-operator + namespace: openshift-console +spec: + replicas: 1 + selector: + matchLabels: + name: console-operator + template: + metadata: + labels: + name: console-operator + spec: + serviceAccountName: console-operator + containers: + - name: console-operator + image: docker.io/openshift/origin-console-operator:latest + ports: + - containerPort: 60000 + name: metrics + command: + - console-operator + args: + - "-create-default-console=true" + imagePullPolicy: Always + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: IMAGE + value: docker.io/openshift/origin-console:latest + - name: OPERATOR_NAME + value: "console-operator" diff --git a/manifests/clusterrole.yaml b/manifests/clusterrole.yaml deleted file mode 100644 index 6cd255f..0000000 --- a/manifests/clusterrole.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: system:openshift:controller:service-ca -rules: -- apiGroups: - - "" - resources: - - secrets - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - deletecollection -- apiGroups: - - "" - resources: - - services - verbs: - - get - - list - - watch - - update - - patch diff --git a/manifests/clusterrolebinding.yaml b/manifests/clusterrolebinding.yaml deleted file mode 100644 index 7e8a77c..0000000 --- a/manifests/clusterrolebinding.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: system:openshift:controller:service-ca -roleRef: - kind: ClusterRole - name: system:openshift:controller:service-ca -subjects: -- kind: ServiceAccount - namespace: openshift-service-ca - name: service-ca-sa diff --git a/manifests/cm.yaml b/manifests/cm.yaml deleted file mode 100644 index 98d3063..0000000 --- a/manifests/cm.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: openshift-service-ca - name: service-ca-config -data: - controller-config.yaml: diff --git a/manifests/defaultconfig.yaml b/manifests/defaultconfig.yaml deleted file mode 100644 index f01ef8e..0000000 --- a/manifests/defaultconfig.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: servicecertsigner.config.openshift.io/v1alpha1 -kind: ServiceServingCertSignerConfig -signer: - certFile: /var/run/secrets/signing-key/tls.crt - keyFile: /var/run/secrets/signing-key/tls.key diff --git a/manifests/deployment.yaml b/manifests/deployment.yaml deleted file mode 100644 index 5304dd0..0000000 --- a/manifests/deployment.yaml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - namespace: openshift-service-ca - name: service-ca - labels: - app: openshift-service-ca - service-ca: "true" -spec: - strategy: - type: Recreate - selector: - matchLabels: - app: openshift-service-ca - service-ca: "true" - template: - metadata: - name: service-ca - labels: - app: openshift-service-ca - service-ca: "true" - spec: - serviceAccountName: service-ca-sa - containers: - - name: service-ca-controller - image: ${IMAGE} - imagePullPolicy: IfNotPresent - command: ["service-ca", "serving-cert-signer"] - args: - - "--config=/var/run/configmaps/config/controller-config.yaml" - ports: - - containerPort: 8443 - volumeMounts: - - mountPath: /var/run/configmaps/config - name: config - - mountPath: /var/run/secrets/signing-key - name: signing-key - - mountPath: /var/run/secrets/serving-cert - name: serving-cert - volumes: - - name: serving-cert - secret: - secretName: service-ca-serving-cert - optional: true - - name: signing-key - secret: - secretName: service-ca-signing-key - - name: config - configMap: - name: service-ca-config - - - diff --git a/manifests/image-references b/manifests/image-references new file mode 100644 index 0000000..d5c9b30 --- /dev/null +++ b/manifests/image-references @@ -0,0 +1,13 @@ +kind: ImageStream +apiVersion: image.openshift.io/v1 +spec: + tags: + - name: console-operator + from: + kind: DockerImage + name: docker.io/openshift/origin-console-operator:latest + - name: console + from: + kind: DockerImage + name: docker.io/openshift/origin-console:latest + diff --git a/manifests/ns.yaml b/manifests/ns.yaml deleted file mode 100644 index c637fd0..0000000 --- a/manifests/ns.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: openshift-service-ca - labels: - openshift.io/run-level: "1" \ No newline at end of file diff --git a/manifests/sa.yaml b/manifests/sa.yaml deleted file mode 100644 index 99abb44..0000000 --- a/manifests/sa.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - namespace: openshift-service-ca - name: service-ca-sa diff --git a/manifests/signing-secret.yaml b/manifests/signing-secret.yaml deleted file mode 100644 index d4cc35a..0000000 --- a/manifests/signing-secret.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - namespace: openshift-service-ca - name: service-ca-signing-key -type: kubernetes.io/tls -data: - tls.crt: - tls.key: diff --git a/manifests/svc.yaml b/manifests/svc.yaml deleted file mode 100644 index 6e1d504..0000000 --- a/manifests/svc.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - namespace: openshift-service-ca - name: service-ca - annotations: - service.alpha.openshift.io/serving-cert-secret-name: service-ca-serving-cert - prometheus.io/scrape: "true" - prometheus.io/scheme: https -spec: - selector: - service-ca: "true" - ports: - - name: https - port: 443 - targetPort: 8443 From 0211c3ff55acb97c5662561f77aa7d5a6d1c9b1a Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Wed, 7 Nov 2018 14:23:52 -0500 Subject: [PATCH 03/24] Update Dockerfile & create Dockerfile.osx for local --- Dockerfile | 31 +++++++++++++++++++++++-------- Dockerfile.osx | 27 +++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 Dockerfile.osx diff --git a/Dockerfile b/Dockerfile index f91bf49..23f2df1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,25 @@ -# This is an console operator. -# -# The standard name for its image is enj/console-operator -# -FROM openshift/origin-release:golang-1.10 -COPY . /go/src/github.com/enj/example-operator -RUN cd /go/src/github.com/enj/example-operator && go build ./cmd/example +FROM openshift/origin-release:golang-1.10 as builder +WORKDIR /go/src/github.com/openshift/console-operator +COPY . . +RUN make build FROM centos:7 -COPY --from=0 /go/src/github.com/enj/example-operator/example /usr/bin/example +RUN useradd console-operator +USER console-operator +COPY --from=builder /go/src/github.com/openshift/console-operator/_output/local/bin/linux/amd64/console /usr/bin + +# these manifests are necessary for the installer +COPY manifests /manifests/ + +LABEL io.k8s.display-name="OpenShift console-operator" \ + io.k8s.description="This is a component of OpenShift Container Platform and manages the lifecycle of the web console." \ + io.openshift.tags="openshift" \ + maintainer="Benjamin A. Petersen " + +LABEL io.openshift.release.operator true + +# entrypoint specified in 03-operator.yaml as `console-operator` +# CMD ["/usr/bin/console", "operator", "--kubeconfig", "path/to/config", "--config", "./install/config.yaml", "--v", "4"] +CMD ["/usr/bin/console", "operator", "--v", "4"] + + diff --git a/Dockerfile.osx b/Dockerfile.osx new file mode 100644 index 0000000..857a0cb --- /dev/null +++ b/Dockerfile.osx @@ -0,0 +1,27 @@ +FROM openshift/origin-release:golang-1.10 as builder +WORKDIR /go/src/github.com/openshift/console-operator +COPY . . +RUN make build + +FROM centos:7 +RUN useradd console-operator +USER console-operator +COPY --from=builder /go/src/github.com/openshift/console-operator/_output/local/bin/darwin/amd64/console /usr/bin + +# these manifests are necessary for the installer +COPY manifests /manifests/ + +LABEL io.k8s.display-name="OpenShift console-operator" \ + io.k8s.description="This is a component of OpenShift Container Platform and manages the lifecycle of the web console." \ + io.openshift.tags="openshift" \ + maintainer="Benjamin A. Petersen " + +LABEL io.openshift.release.operator true + +# entrypoint specified in 03-operator.yaml as `console-operator` +# CMD ["/usr/bin/console", "operator", "--kubeconfig", "path/to/config", "--config", "./install/config.yaml", "--v", "4"] +CMD ["/usr/bin/console", "operator", "--v", "4"] + + + + From dde0e00a7e89402f80bacfb572233e081db48081 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Wed, 7 Nov 2018 14:39:18 -0500 Subject: [PATCH 04/24] Adding back examples/config.yaml as this will likely be needed --- examples/config.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 examples/config.yaml diff --git a/examples/config.yaml b/examples/config.yaml new file mode 100644 index 0000000..3eb2b1d --- /dev/null +++ b/examples/config.yaml @@ -0,0 +1,4 @@ +apiVersion: operator.openshift.io/v1alpha1 +kind: GenericOperatorConfig +leaderElection: + namespace: openshift-console From a1dd54d58e90e8dc241f8fd95308f583eca14e11 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Wed, 7 Nov 2018 14:40:04 -0500 Subject: [PATCH 05/24] Update README to include expected flags & build/run process --- README.md | 87 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index bf6631f..812fb11 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,84 @@ -# Example Operator +# Console Operator -```shell -cd "${GOPATH}/src/github.com/enj/example-operator" +An operator for OpenShift Console built using the operator-sdk. -oc new-project example-operator +The console-operator installs and maintains the web console on a cluster. -oc create -f manifests/00-crd.yaml -oc create -f install/cr.yaml +## Run on a 4.0.0 cluster +The console operator is installed by default and will automatically maintain a console. + +## Development Setup + +* Install Go -- https://golang.org/doc/install + +## Development on a < 4.0.0 cluster + +If using `oc cluster up` on a `< 4.0.0` cluster you will need the `--public-hostname` flag +when you cluster up. The `--server-loglevel` flag is helpful for debugging. OAuth issues +will not be visible unless set to at least `3`. + +```bash +# there are a variety of ways to get your machine IP address +# this example works on OSX +oc cluster up --public-hostname=$(ipconfig getifaddr en0) --server-loglevel 3 +``` + +Then, create the manifests: + +```bash +# pre 4.0.0 needs this, but it is not part of the post 4.0.0 manifests payload +oc create -f ./examples/crd-clusteroperator.yaml +# standard 4.0.0 deploy of the operator +oc create -f ./manifests +# to run the operator locally, delete the deployment and follow instructions below +oc delete -f ./manifests/05-operator.yaml +``` + +If you don't know where your `kubeconfig` file is: + +```bash +# just a high number +oc whoami --loglevel=100 +# likely output will be $HOME/.kube/config +``` + +Build the console operator binary: + +```bash +make update-codegen make -export PATH="_output/local/bin/linux/amd64:${PATH}" -example operator --kubeconfig admin.kubeconfig --config install/config.yaml --v=4 +make verify +# add the binary to your path +# arc will be "linux" or "darwin", etc +export PATH="_output/local/bin//amd64:${PATH}" +``` + +Now, run the console operator locally: + +```bash +IMAGE=docker.io/openshift/origin-console:latest \ + console operator \ + --kubeconfig $HOME/.kube/config \ + --config examples/config.yaml \ + --create-default-console \ + --v 4 +``` -oc get exampleoperator example-operator-resource -o yaml -oc get secret example-operator-resource -o yaml +Check for the existence of expected resources: + +```bash +oc get console +# etc ``` + + +Explanation: + +- The `IMAGE` env var is needed to declare what console image to deploy. The `manifests/05-operator.yaml` shows this var as well +- The `--operator-flags` flag is used to pass flags to the operator binary + - `--create-default-console true` tells the operator binary to create a console CR if one does not exist on startup. + +The `IMAGE` env var exists so that when the console-operator is packaged up for a release, we can replace the value +with a final image. See CVO documentation for details. + From 030787e6e2441524f8e274cdce7c7bb6caf93656 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Wed, 7 Nov 2018 16:04:03 -0500 Subject: [PATCH 06/24] Add `console version` command --- cmd/console/main.go | 12 +++++++++++- pkg/cmd/version/cmd.go | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/cmd/console/main.go b/cmd/console/main.go index 295bc62..73a73aa 100644 --- a/cmd/console/main.go +++ b/cmd/console/main.go @@ -15,25 +15,34 @@ import ( "k8s.io/apiserver/pkg/util/logs" // us "github.com/openshift/console-operator/pkg/cmd/operator" + "github.com/openshift/console-operator/pkg/cmd/version" ) func main() { + // random seed, set it & forget it rand.Seed(time.Now().UTC().UnixNano()) - + // normalize flags, if _ use - pflag.CommandLine.SetNormalizeFunc(utilflag.WordSepNormalizeFunc) + // add the default flag set for go pflag.CommandLine.AddGoFlagSet(goflag.CommandLine) logs.InitLogs() defer logs.FlushLogs() + // build a new cobra command command := NewOperatorCommand() + // die on errors if err := command.Execute(); err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(1) } } +// create the root "console" command +// we will add subcommands to this func NewOperatorCommand() *cobra.Command { + // "console" just prints help, then exists. It doesn't start + // the operator. cmd := &cobra.Command{ Use: "console", Short: "Top level command", @@ -44,6 +53,7 @@ func NewOperatorCommand() *cobra.Command { } cmd.AddCommand(operator.NewOperator()) + cmd.AddCommand(version.NewVersion()) return cmd } diff --git a/pkg/cmd/version/cmd.go b/pkg/cmd/version/cmd.go index f37d99d..f99d554 100644 --- a/pkg/cmd/version/cmd.go +++ b/pkg/cmd/version/cmd.go @@ -1 +1,25 @@ package version + +import ( + "fmt" + "strings" + "github.com/blang/semver" + "github.com/spf13/cobra" +) + +var ( + Raw = "v0.0.1" + Version = semver.MustParse(strings.TrimLeft(Raw, "v")) + String = fmt.Sprintf("ConsoleOperator %s", Raw) +) + +func NewVersion() *cobra.Command { + cmd := &cobra.Command{ + Use: "version", + Short: "Display the Operator Version", + Run: func(command *cobra.Command, args []string) { + fmt.Println(String) + }, + } + return cmd +} From e49a05482498a72e911401cd11581d3d0d58100e Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Wed, 7 Nov 2018 16:04:39 -0500 Subject: [PATCH 07/24] Add some dev_*.sh scripts --- dev_delete_all.sh | 49 ++++++++++++++++++++++++++++ dev_deploy_all.sh | 59 ++++++++++++++++++++++++++++++++++ dev_run_local.sh | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 189 insertions(+) create mode 100755 dev_delete_all.sh create mode 100755 dev_deploy_all.sh create mode 100755 dev_run_local.sh diff --git a/dev_delete_all.sh b/dev_delete_all.sh new file mode 100755 index 0000000..fd5c7bc --- /dev/null +++ b/dev_delete_all.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +# this just deletes everything under /manifests, +# but tries to space them out a bit to avoid errors. +# in the end, it creates a custom resource to kick +# the operator into action + +FILE=examples/cr.yaml +echo "creating ${FILE}" +oc create -f $FILE + +for FILE in `find ./manifests -name '05-*'` +do + echo "deleting ${FILE}" + oc create -f $FILE +done + +for FILE in `find ./manifests -name '04-*'` +do + echo "deleting ${FILE}" + oc create -f $FILE +done + +for FILE in `find ./manifests -name '03-*'` +do + echo "deleting ${FILE}" + oc create -f $FILE +done + +for FILE in `find ./manifests -name '02-*'` +do + echo "deleting ${FILE}" + oc create -f $FILE +done + +for FILE in `find ./manifests -name '01-*'` +do + echo "deleting ${FILE}" + oc create -f $FILE +done + +for FILE in `find ./manifests -name '00-*'` +do + echo "deleting ${FILE}" + oc create -f $FILE +done + + + diff --git a/dev_deploy_all.sh b/dev_deploy_all.sh new file mode 100755 index 0000000..703c5eb --- /dev/null +++ b/dev_deploy_all.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash + +# this just deploys everything under /manifests, +# but tries to space them out a bit to avoid errors. +# in the end, it creates a custom resource to kick +# the operator into action + +for FILE in `find ./manifests -name '00-*'` +do + echo "creating ${FILE}" + oc create -f $FILE +done + +sleep 2 + +for FILE in `find ./manifests -name '01-*'` +do + echo "creating ${FILE}" + oc create -f $FILE +done + +sleep 2 + +for FILE in `find ./manifests -name '02-*'` +do + echo "creating ${FILE}" + oc create -f $FILE +done + +sleep 2 + +for FILE in `find ./manifests -name '03-*'` +do + echo "creating ${FILE}" + oc create -f $FILE +done + +sleep 2 + +for FILE in `find ./manifests -name '04-*'` +do + echo "creating ${FILE}" + oc create -f $FILE +done + +sleep 2 + +for FILE in `find ./manifests -name '05-*'` +do + echo "creating ${FILE}" + oc create -f $FILE +done + +sleep 2 + + +FILE=examples/cr.yaml +echo "creating ${FILE}" +oc create -f $FILE diff --git a/dev_run_local.sh b/dev_run_local.sh new file mode 100755 index 0000000..18e9e94 --- /dev/null +++ b/dev_run_local.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +# this just deploys everything under /manifests, +# but tries to space them out a bit to avoid errors. +# in the end, it creates a custom resource to kick +# the operator into action + +# necessary if doing dev locally on a < 4.0.0 cluster +CLUSTER_OPERATOR_CRD_FILE="./examples/crd-clusteroperator.yaml" +echo "creating ${CLUSTER_OPERATOR_CRD_FILE}" +oc create -f "${CLUSTER_OPERATOR_CRD_FILE}" + +# examples/cr.yaml is not necessary as the operator will create +# an instance of a "console" by default. +# use it if customization is desired. + +for FILE in `find ./manifests -name '00-*'` +do + echo "creating ${FILE}" + oc create -f $FILE +done + +sleep 1 + +for FILE in `find ./manifests -name '01-*'` +do + echo "creating ${FILE}" + oc create -f $FILE +done + +sleep 2 + +for FILE in `find ./manifests -name '02-*'` +do + echo "creating ${FILE}" + oc create -f $FILE +done + +sleep 1 + +for FILE in `find ./manifests -name '03-*'` +do + echo "creating ${FILE}" + oc create -f $FILE +done + +sleep 1 + +for FILE in `find ./manifests -name '04-*'` +do + echo "creating ${FILE}" + oc create -f $FILE +done + +sleep 1 + +# Don't deploy the operator in `manifests` +# instead, we will instantiate the operator locally +# +#for FILE in `find ./manifests -name '05-*'` +#do +# echo "creating ${FILE}" +# oc create -f $FILE +#done +IMAGE=docker.io/openshift/origin-console:latest \ + console operator \ + --kubeconfig $HOME/.kube/config \ + --config examples/config.yaml \ + --v 4 + +echo "TODO: support --create-default-console again!" + +# TODO: GET BACK TO THIS: +#IMAGE=docker.io/openshift/origin-console:latest \ +# console operator \ +# --kubeconfig $HOME/.kube/config \ +# --config examples/config.yaml \ +# --create-default-console \ +# --v 4 + + From 1012bf3bdae9ee0a7b657967fa645883b0efbfc2 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Wed, 7 Nov 2018 21:33:37 -0500 Subject: [PATCH 08/24] Update README --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 812fb11..973ee1a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Console Operator -An operator for OpenShift Console built using the operator-sdk. +An operator for OpenShift Console. The console-operator installs and maintains the web console on a cluster. @@ -72,7 +72,6 @@ oc get console # etc ``` - Explanation: - The `IMAGE` env var is needed to declare what console image to deploy. The `manifests/05-operator.yaml` shows this var as well From 848530d0bdcc26ea6f7bd5b20fcb9d20dc35eab8 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Wed, 7 Nov 2018 21:34:03 -0500 Subject: [PATCH 09/24] Add dev_delete_all.sh hack script --- dev_delete_all.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dev_delete_all.sh b/dev_delete_all.sh index fd5c7bc..ee299ef 100755 --- a/dev_delete_all.sh +++ b/dev_delete_all.sh @@ -7,42 +7,42 @@ FILE=examples/cr.yaml echo "creating ${FILE}" -oc create -f $FILE +oc delete -f $FILE for FILE in `find ./manifests -name '05-*'` do echo "deleting ${FILE}" - oc create -f $FILE + oc delete -f $FILE done for FILE in `find ./manifests -name '04-*'` do echo "deleting ${FILE}" - oc create -f $FILE + oc delete -f $FILE done for FILE in `find ./manifests -name '03-*'` do echo "deleting ${FILE}" - oc create -f $FILE + oc delete -f $FILE done for FILE in `find ./manifests -name '02-*'` do echo "deleting ${FILE}" - oc create -f $FILE + oc delete -f $FILE done for FILE in `find ./manifests -name '01-*'` do echo "deleting ${FILE}" - oc create -f $FILE + oc delete -f $FILE done for FILE in `find ./manifests -name '00-*'` do echo "deleting ${FILE}" - oc create -f $FILE + oc delete -f $FILE done From b778e5d793d609b7a5d90c430aedfc5c48a3bba4 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Thu, 8 Nov 2018 15:57:48 -0500 Subject: [PATCH 10/24] Comment on dev_run_local.sh --- dev_run_local.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dev_run_local.sh b/dev_run_local.sh index 18e9e94..12928f5 100755 --- a/dev_run_local.sh +++ b/dev_run_local.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash + +echo "login as system:admin to install...." + # this just deploys everything under /manifests, # but tries to space them out a bit to avoid errors. # in the end, it creates a custom resource to kick @@ -54,6 +57,8 @@ done sleep 1 +echo "did you 'make build' the latest binary?" + # Don't deploy the operator in `manifests` # instead, we will instantiate the operator locally # From c3eb95c14ead8c1ec0658981a2f1901ab162190d Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Thu, 8 Nov 2018 16:01:27 -0500 Subject: [PATCH 11/24] Add todo to version command --- pkg/cmd/version/cmd.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/cmd/version/cmd.go b/pkg/cmd/version/cmd.go index f99d554..a45e77d 100644 --- a/pkg/cmd/version/cmd.go +++ b/pkg/cmd/version/cmd.go @@ -14,6 +14,9 @@ var ( ) func NewVersion() *cobra.Command { + // TODO: + // update & use the pkg/version/version.go to pull + // git information & present here. cmd := &cobra.Command{ Use: "version", Short: "Display the Operator Version", From 45e1fb321bff2545b4c02f6258e5647858bf9597 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Thu, 8 Nov 2018 16:02:09 -0500 Subject: [PATCH 12/24] Add comment to cmd/operator/cmd.go --- pkg/cmd/operator/cmd.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/operator/cmd.go b/pkg/cmd/operator/cmd.go index 5032e68..f123961 100644 --- a/pkg/cmd/operator/cmd.go +++ b/pkg/cmd/operator/cmd.go @@ -12,10 +12,17 @@ import ( func NewOperator() *cobra.Command { cmd := controllercmd. - NewControllerCommandConfig("console-operator", version.Get(), starter.RunOperator). + NewControllerCommandConfig( + "console-operator", + version.Get(), + starter.RunOperator). NewCommand() cmd.Use = "operator" cmd.Short = "Start the Console Operator" - + // TODO: better docs on this + // should probably give example usage, etc + // https://github.com/spf13/cobra#create-rootcmd + cmd.Long = `An Operator for a web console for OpenShift. + ` return cmd } From ab8a72142f662ea20a47b3107ed23af2c405be93 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Thu, 8 Nov 2018 16:06:51 -0500 Subject: [PATCH 13/24] Update dev_run_local.sh (f) --- dev_run_local.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dev_run_local.sh b/dev_run_local.sh index 12928f5..b336fd1 100755 --- a/dev_run_local.sh +++ b/dev_run_local.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash - -echo "login as system:admin to install...." +# we need to be system admin to install these +oc login -u system:admin # this just deploys everything under /manifests, # but tries to space them out a bit to avoid errors. @@ -57,7 +57,11 @@ done sleep 1 -echo "did you 'make build' the latest binary?" +# at this point, we should no longer be system:admin +# oc login -u developer -p 12345 + +# ensure the latest binary has been built +make build # Don't deploy the operator in `manifests` # instead, we will instantiate the operator locally From 51e05a14aab0e4cff5f5ed704233b86f1d4df9c5 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Thu, 8 Nov 2018 16:07:26 -0500 Subject: [PATCH 14/24] Create ClusterOperatorStatus in starter.go --- pkg/console/starter/starter.go | 107 ++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 35 deletions(-) diff --git a/pkg/console/starter/starter.go b/pkg/console/starter/starter.go index 45a9c1b..92d73e2 100644 --- a/pkg/console/starter/starter.go +++ b/pkg/console/starter/starter.go @@ -2,28 +2,50 @@ package starter import ( "fmt" - "github.com/openshift/library-go/pkg/operator/status" - "k8s.io/client-go/dynamic" - "k8s.io/client-go/tools/cache" "time" + "k8s.io/client-go/tools/cache" "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" + "k8s.io/client-go/dynamic" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + "github.com/openshift/library-go/pkg/operator/status" + operatorv1alpha1 "github.com/openshift/api/operator/v1alpha1" "github.com/openshift/console-operator/pkg/console/operator" "github.com/openshift/console-operator/pkg/generated/clientset/versioned" "github.com/openshift/console-operator/pkg/generated/informers/externalversions" ) + +// Time to wire up our informers/clients/etc +// +// informers +// - listen for changes +// +// clients +// - used by informers to get,list,put resources +// +// informers +// - instantiated in starter.go (here) +// - consumed in... places. func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { + + fmt.Printf("starter.go -> RunOperator() func........\n") + + // creates a new kube clientset + // clientConfig is a REST config + // a clientSet contains clients for groups. + // each group has one version included in the set. kubeClient, err := kubernetes.NewForConfig(clientConfig) if err != nil { return err } + // pkg/apis/console/v1alpha1/types.go has a `genclient` annotation, + // that creates the expected functions for the type. consoleOperatorClient, err := versioned.NewForConfig(clientConfig) if err != nil { return err @@ -32,24 +54,39 @@ func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { const resync = 10 * time.Minute // only watch a specific resource name + // this is an optimization step that is not initially needed + // TODO: eliminate for now? tweakListOptions := func(options *v1.ListOptions) { options.FieldSelector = fields.OneTermEqualSelector("metadata.name", operator.ResourceName).String() } - kubeInformersNamespaced := informers.NewSharedInformerFactoryWithOptions(kubeClient, resync, + kubeInformersNamespaced := informers.NewSharedInformerFactoryWithOptions( + // takes a client + kubeClient, + resync, + // takes an unlimited number of additional "options" arguments, which are functions, + // that take a sharedInformerFactory and return a sharedInformerFactory informers.WithNamespace(operator.TargetNamespace), informers.WithTweakListOptions(tweakListOptions), ) - consoleOperatorInformers := externalversions.NewSharedInformerFactoryWithOptions(consoleOperatorClient, resync, + consoleOperatorInformers := externalversions.NewSharedInformerFactoryWithOptions( + // this is our generated client + consoleOperatorClient, + resync, + // and the same set of optional transform functions externalversions.WithNamespace(operator.TargetNamespace), externalversions.WithTweakListOptions(tweakListOptions), ) consoleOperator := operator.NewConsoleOperator( + // informer factory, drilling down to the v1alpha1 console informer consoleOperatorInformers.Console().V1alpha1().Consoles(), + // specifically secrets, we can add more here. kubeInformersNamespaced.Core().V1().Secrets(), + // client and informer are NOT the same consoleOperatorClient.ConsoleV1alpha1().Consoles(operator.TargetNamespace), + // client and informer are NOT the same kubeClient.CoreV1(), ) @@ -68,17 +105,18 @@ func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { // to test this, will need to update STATUS on my CR // and then check and see if it is updated on the other deal. // TODO: install this, from the old console-operator install operatorstatus.openshift.io - //clusterOperatorStatus := status.NewClusterOperatorStatusController( - // // what are these? name of controller(operator)? wire this up. - // "openshift-apiserver", - // "openshift-apiserver", - // // what is this - // dynamicClient, - // &operatorStatusProvider{informers: operatorConfigInformers}, - //) - // - //// TODO: will have a series of runs here - //go clusterOperatorStatus.Run(1, stopCh) + clusterOperatorStatus := status.NewClusterOperatorStatusController( + // TODO: these may not be exactly right... + // make sure they are what we actually need. + operator.TargetNamespace, + operator.ResourceName, + // for some reason we need a dynamic client. this is weird, and i dont know why + // given that we rant about "real" strongly typed clients constantly. + dynamicClient, + &operatorStatusProvider{informers: consoleOperatorInformers}, + ) + // TODO: will have a series of Run() funcs here + go clusterOperatorStatus.Run(1, stopCh) <-stopCh @@ -86,23 +124,22 @@ func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { } +// NOTE: i want this in a separate package, +// but most other operators seem to keep it here :/ +type operatorStatusProvider struct { + informers externalversions.SharedInformerFactory +} + +func (p *operatorStatusProvider) Informer() cache.SharedIndexInformer { + return p.informers.Console().V1alpha1().Consoles().Informer() +} + +func (p *operatorStatusProvider) CurrentStatus() (operatorv1alpha1.OperatorStatus, error) { + instance, err := p.informers.Console().V1alpha1().Consoles().Lister().Consoles(operator.TargetNamespace).Get(operator.ResourceName) + if err != nil { + return operatorv1alpha1.OperatorStatus{}, err + } + + return instance.Status.OperatorStatus, nil +} -// Interface -//type operatorStatusProvider struct { -// informers operatorclientinformers.SharedInformerFactory -//} -// -//func (p *operatorStatusProvider) Informer() cache.SharedIndexInformer { -// // TODO: return my informaer.... -// // return p.informers.Openshiftapiserver().V1alpha1().OpenShiftAPIServerOperatorConfigs().Informer() -//} -// -//func (p *operatorStatusProvider) CurrentStatus() (operatorv1alpha1.OperatorStatus, error) { -// // TODO: use my informer to get my status -// instance, err := p.informers.Openshiftapiserver().V1alpha1().OpenShiftAPIServerOperatorConfigs().Lister().Get("instance") -// if err != nil { -// return operatorv1alpha1.OperatorStatus{}, err -// } -// -// return instance.Status.OperatorStatus, nil -//} From 1c0cbc717a686f869939f5690850f952ce85143c Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Thu, 8 Nov 2018 23:52:36 -0500 Subject: [PATCH 15/24] Add all clients, informers to starter, operator --- pkg/console/operator/operator.go | 79 +++++++++++++++++++++--- pkg/console/starter/starter.go | 101 ++++++++++++++++++------------- 2 files changed, 131 insertions(+), 49 deletions(-) diff --git a/pkg/console/operator/operator.go b/pkg/console/operator/operator.go index 1d277e8..afce289 100644 --- a/pkg/console/operator/operator.go +++ b/pkg/console/operator/operator.go @@ -12,16 +12,24 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/informers/core/v1" coreclientv1 "k8s.io/client-go/kubernetes/typed/core/v1" + appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" operatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1" "github.com/openshift/library-go/pkg/operator/resource/resourceapply" "github.com/openshift/library-go/pkg/operator/versioning" - - "github.com/openshift/console-operator/pkg/controller" - "github.com/openshift/console-operator/pkg/generated/clientset/versioned/typed/console/v1alpha1" + // informers + routesinformersv1 "github.com/openshift/client-go/route/informers/externalversions/route/v1" + appsinformersv1 "k8s.io/client-go/informers/apps/v1" + oauthinformersv1 "github.com/openshift/client-go/oauth/informers/externalversions/oauth/v1" consoleinformers "github.com/openshift/console-operator/pkg/generated/informers/externalversions/console/v1alpha1" + // clients + "github.com/openshift/console-operator/pkg/generated/clientset/versioned/typed/console/v1alpha1" + routeclientv1 "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1" + oauthclientv1 "github.com/openshift/client-go/oauth/clientset/versioned/typed/oauth/v1" + // operator + "github.com/openshift/console-operator/pkg/controller" ) const ( @@ -37,23 +45,69 @@ const ( workQueueKey = "key" ) -func NewConsoleOperator(coi consoleinformers.ConsoleInformer, si v1.SecretInformer, operatorClient v1alpha1.ConsoleInterface, secretsClient coreclientv1.SecretsGetter) *ConsoleOperator { +// func NewConsoleOperator( +// coi consoleinformers.ConsoleOperatorInformer, +// si v1.SecretInformer, +// operatorClient v1alpha1.ConsoleOperatorInterface, +// secretsClient coreclientv1.SecretsGetter) *ConsoleOperator { +func NewConsoleOperator( + // informers + coi consoleinformers.ConsoleInformer, + coreV1 v1.Interface, + appsV1 appsinformersv1.Interface, + routesV1 routesinformersv1.Interface, + oauthV1 oauthinformersv1.Interface, + // clients + operatorClient v1alpha1.ConsoleInterface, + corev1Client coreclientv1.CoreV1Interface, + appsv1Client appsv1.AppsV1Interface, + routev1Client routeclientv1.RouteV1Interface, + oauthv1Client oauthclientv1.OauthV1Interface) *ConsoleOperator { + + c := &ConsoleOperator{ + // operator operatorClient: operatorClient, - secretsClient: secretsClient, + // core kube + secretsClient: corev1Client, + configMapClient: corev1Client, + serviceClient: corev1Client, + deploymentClient: appsv1Client, + // openshift + routeClient: routev1Client, + oauthClient: oauthv1Client, } operatorInformer := coi.Informer() - secretsInformer := si.Informer() + secretsInformer := coreV1.Secrets().Informer() + deploymentInformer := appsV1.Deployments().Informer() + configMapInformer := coreV1.ConfigMaps().Informer() + serviceInformer := coreV1.Services().Informer() + routeInformer := routesV1.Routes().Informer() + oauthInformer := oauthV1.OAuthClientAuthorizations().Informer() // we do not really need to wait for our informers to sync since we only watch a single resource // and make live reads but it does not hurt anything and guarantees we have the correct behavior - internalController, queue := controller.New("Console", c.sync, operatorInformer.HasSynced, secretsInformer.HasSynced) + internalController, queue := controller.New( + "Console", + c.sync, + operatorInformer.HasSynced, + secretsInformer.HasSynced, + deploymentInformer.HasSynced, + configMapInformer.HasSynced, + serviceInformer.HasSynced, + routeInformer.HasSynced, + oauthInformer.HasSynced) c.controller = internalController operatorInformer.AddEventHandler(eventHandler(queue)) secretsInformer.AddEventHandler(eventHandler(queue)) + deploymentInformer.AddEventHandler(eventHandler(queue)) + configMapInformer.AddEventHandler(eventHandler(queue)) + serviceInformer.AddEventHandler(eventHandler(queue)) + routeInformer.AddEventHandler(eventHandler(queue)) + oauthInformer.AddEventHandler(eventHandler(queue)) return c } @@ -75,8 +129,15 @@ type ConsoleOperator struct { // to handle reads and clients to handle writes. since this operator works // on a singleton resource, it has no performance requirements. operatorClient v1alpha1.ConsoleInterface + // core kube secretsClient coreclientv1.SecretsGetter - + configMapClient coreclientv1.ConfigMapsGetter + serviceClient coreclientv1.ServicesGetter + deploymentClient appsv1.DeploymentsGetter + // openshift + routeClient routeclientv1.RoutesGetter + oauthClient oauthclientv1.OAuthClientsGetter + // controller controller *controller.Controller } @@ -86,6 +147,8 @@ func (c *ConsoleOperator) Run(stopCh <-chan struct{}) { c.controller.Run(1, stopCh) } +// sync() is the handler() function equivalent from the sdk +// this is the big switch statement. func (c *ConsoleOperator) sync(_ interface{}) error { // we ignore the passed in key because it will always be workQueueKey // it does not matter how the sync loop was triggered diff --git a/pkg/console/starter/starter.go b/pkg/console/starter/starter.go index 92d73e2..25bfdb9 100644 --- a/pkg/console/starter/starter.go +++ b/pkg/console/starter/starter.go @@ -6,34 +6,35 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/fields" + // "k8s.io/apimachinery/pkg/fields" "k8s.io/client-go/dynamic" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "github.com/openshift/library-go/pkg/operator/status" - operatorv1alpha1 "github.com/openshift/api/operator/v1alpha1" - "github.com/openshift/console-operator/pkg/console/operator" + + // clients + routesclient "github.com/openshift/client-go/route/clientset/versioned" + authclient "github.com/openshift/client-go/oauth/clientset/versioned" "github.com/openshift/console-operator/pkg/generated/clientset/versioned" + // informers + oauthinformers "github.com/openshift/client-go/oauth/informers/externalversions" + routesinformers "github.com/openshift/client-go/route/informers/externalversions" "github.com/openshift/console-operator/pkg/generated/informers/externalversions" + + operatorv1alpha1 "github.com/openshift/api/operator/v1alpha1" + "github.com/openshift/console-operator/pkg/console/operator" ) -// Time to wire up our informers/clients/etc -// -// informers -// - listen for changes -// -// clients -// - used by informers to get,list,put resources -// -// informers -// - instantiated in starter.go (here) -// - consumed in... places. func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { - fmt.Printf("starter.go -> RunOperator() func........\n") + // only for the ClusterStatus, everything else has a specific client + dynamicClient, err := dynamic.NewForConfig(clientConfig) + if err != nil { + return err + } // creates a new kube clientset // clientConfig is a REST config @@ -51,13 +52,24 @@ func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { return err } + routesClient, err := routesclient.NewForConfig(clientConfig) + if err != nil { + return err + } + + oauthClient, err := authclient.NewForConfig(clientConfig) + if err != nil { + return err + } + const resync = 10 * time.Minute - // only watch a specific resource name - // this is an optimization step that is not initially needed - // TODO: eliminate for now? + // NOOP for now + // TODO: can perhaps put this back the way it was, but may + // need to create a couple different version for + // resources w/different names tweakListOptions := func(options *v1.ListOptions) { - options.FieldSelector = fields.OneTermEqualSelector("metadata.name", operator.ResourceName).String() + // options.FieldSelector = fields.OneTermEqualSelector("metadata.name", operator.ResourceName).String() } kubeInformersNamespaced := informers.NewSharedInformerFactoryWithOptions( @@ -79,39 +91,47 @@ func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { externalversions.WithTweakListOptions(tweakListOptions), ) + routesInformersNamespaced := routesinformers.NewSharedInformerFactoryWithOptions( + routesClient, + resync, + routesinformers.WithNamespace(operator.TargetNamespace), + routesinformers.WithTweakListOptions(tweakListOptions), + ) + + // oauthclients are not namespaced + oauthInformers := oauthinformers.NewSharedInformerFactoryWithOptions( + oauthClient, + resync, + oauthinformers.WithTweakListOptions(tweakListOptions), + ) + consoleOperator := operator.NewConsoleOperator( - // informer factory, drilling down to the v1alpha1 console informer - consoleOperatorInformers.Console().V1alpha1().Consoles(), - // specifically secrets, we can add more here. - kubeInformersNamespaced.Core().V1().Secrets(), - // client and informer are NOT the same + // informers + consoleOperatorInformers.Console().V1alpha1().Consoles(), // Console + kubeInformersNamespaced.Core().V1(), // Secrets, ConfigMaps, Service + kubeInformersNamespaced.Apps().V1(), // Deployments + routesInformersNamespaced.Route().V1(), // Route + oauthInformers.Oauth().V1(), // oauth + // clients consoleOperatorClient.ConsoleV1alpha1().Consoles(operator.TargetNamespace), - // client and informer are NOT the same - kubeClient.CoreV1(), + kubeClient.CoreV1(), // Secrets, ConfigMaps, Service + kubeClient.AppsV1(), + routesClient.RouteV1(), + oauthClient.OauthV1(), ) kubeInformersNamespaced.Start(stopCh) consoleOperatorInformers.Start(stopCh) + routesInformersNamespaced.Start(stopCh) + oauthInformers.Start(stopCh) go consoleOperator.Run(stopCh) - // prob move this up... - dynamicClient, err := dynamic.NewForConfig(clientConfig) - if err != nil { - return err - } - // TODO: create the status here.... - // to test this, will need to update STATUS on my CR - // and then check and see if it is updated on the other deal. - // TODO: install this, from the old console-operator install operatorstatus.openshift.io clusterOperatorStatus := status.NewClusterOperatorStatusController( - // TODO: these may not be exactly right... - // make sure they are what we actually need. operator.TargetNamespace, operator.ResourceName, - // for some reason we need a dynamic client. this is weird, and i dont know why - // given that we rant about "real" strongly typed clients constantly. + // no idea why this is dynamic & not a strongly typed client. dynamicClient, &operatorStatusProvider{informers: consoleOperatorInformers}, ) @@ -124,8 +144,7 @@ func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { } -// NOTE: i want this in a separate package, -// but most other operators seem to keep it here :/ +// I'd prefer this in a /console/status/ package, but other operators keep it here. type operatorStatusProvider struct { informers externalversions.SharedInformerFactory } From 4b93caf1683bf855fb278eea57812bdc7430e107 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Wed, 14 Nov 2018 22:48:33 -0500 Subject: [PATCH 16/24] Create default console if CR does not exist --- pkg/console/operator/operator.go | 71 ++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/pkg/console/operator/operator.go b/pkg/console/operator/operator.go index afce289..286eb42 100644 --- a/pkg/console/operator/operator.go +++ b/pkg/console/operator/operator.go @@ -30,6 +30,7 @@ import ( oauthclientv1 "github.com/openshift/client-go/oauth/clientset/versioned/typed/oauth/v1" // operator "github.com/openshift/console-operator/pkg/controller" + consolev1alpha1 "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" ) const ( @@ -38,11 +39,19 @@ const ( // ResourceName could be made configurable if desired // all resources share the same name to make it easier to reason about and to configure single item watches + // NOTE: this must match metadata.name in the CR.yaml else the CR will be ignored ResourceName = "console-operator-resource" // workQueueKey is the singleton key shared by all events // the value is irrelevant - workQueueKey = "key" + workQueueKey = "console-operator-queue-key" +) + +// consts to maintain existing names of various sub-resources +const ( + OpenShiftConsoleName = "openshift-console" + OpenShiftConsoleShortName = "console" + OpenShiftConsoleNamespace = "openshift-console" ) // func NewConsoleOperator( @@ -153,30 +162,32 @@ func (c *ConsoleOperator) sync(_ interface{}) error { // we ignore the passed in key because it will always be workQueueKey // it does not matter how the sync loop was triggered // all we need to worry about is reconciling the state back to what we expect + operatorConfig, err := c.operatorClient.Get(ResourceName, metav1.GetOptions{}) - config, err := c.operatorClient.Get(ResourceName, metav1.GetOptions{}) + if errors.IsNotFound(err) { + _, err := c.operatorClient.Create(c.defaultConsole()) + return err + } if err != nil { return err } - switch config.Spec.ManagementState { + switch operatorConfig.Spec.ManagementState { case operatorsv1alpha1.Managed: // handled below - case operatorsv1alpha1.Unmanaged: return nil - case operatorsv1alpha1.Removed: return utilerrors.FilterOut(c.secretsClient.Secrets(TargetNamespace).Delete(ResourceName, nil), errors.IsNotFound) - default: // TODO should update status - return fmt.Errorf("unknown state: %v", config.Spec.ManagementState) + return fmt.Errorf("unknown state: %v", operatorConfig.Spec.ManagementState) } var currentActualVerion *semver.Version - if ca := config.Status.CurrentAvailability; ca != nil { + // TODO: ca.yaml needs a version, update the v1alpha1.Console to include version field + if ca := operatorConfig.Status.CurrentAvailability; ca != nil { ver, err := semver.Parse(ca.Version) if err != nil { utilruntime.HandleError(err) @@ -184,18 +195,34 @@ func (c *ConsoleOperator) sync(_ interface{}) error { currentActualVerion = &ver } } - desiredVersion, err := semver.Parse(config.Spec.Version) + desiredVersion, err := semver.Parse(operatorConfig.Spec.Version) if err != nil { // TODO report failing status, we may actually attempt to do this in the "normal" error handling return err } - v310_00_to_unknown := versioning.NewRangeOrDie("3.10.0", "3.10.1") - outConfig := config.DeepCopy() + outConfig := operatorConfig.DeepCopy() var errs []error + + fmt.Println("[Version]") + fmt.Printf("Current version: %v, Desired version: %v \n", currentActualVerion, desiredVersion) + fmt.Printf("Between or empty? %v, between? %v", v310_00_to_unknown.BetweenOrEmpty(currentActualVerion), v310_00_to_unknown.Between(&desiredVersion)) + fmt.Println("-------------") + switch { + // TODO: + // Essentially currentActualVersion & desiredVersion matches + // our current version is so it triggers this block. + // once we put a version (4.0.0) it will no longer trigger this block. + // we need an actual v4 + // so + // case is_v400 + // reconcile v400 + // case is_v311_but_upgrading + // upgrade v400 + // etc. case v310_00_to_unknown.BetweenOrEmpty(currentActualVerion) && v310_00_to_unknown.Between(&desiredVersion): _, _, err := resourceapply.ApplySecret(c.secretsClient, &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ @@ -203,7 +230,7 @@ func (c *ConsoleOperator) sync(_ interface{}) error { Namespace: TargetNamespace, }, Data: map[string][]byte{ - config.Spec.Value: []byte("007"), + operatorConfig.Spec.Value: []byte("007"), }, }) errs = append(errs, err) @@ -225,3 +252,23 @@ func (c *ConsoleOperator) sync(_ interface{}) error { return utilerrors.NewAggregate(errs) } + + +func (c *ConsoleOperator) defaultConsole() *consolev1alpha1.Console { + return &consolev1alpha1.Console{ + ObjectMeta: metav1.ObjectMeta{ + // Name: OpenShiftConsoleName, + Name: ResourceName, + Namespace: OpenShiftConsoleNamespace, + }, + Spec: consolev1alpha1.ConsoleSpec{ + OperatorSpec: operatorsv1alpha1.OperatorSpec{ + ManagementState: "Managed", + }, + }, + } +} + + + + From 563299b5506223566710316be6fab4ab729cb986 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Fri, 16 Nov 2018 15:35:45 -0500 Subject: [PATCH 17/24] Update sync loop, add Apply for all subresources --- README.md | 5 + examples/cr.yaml | 7 +- pkg/apis/console/v1alpha1/types.go | 4 +- pkg/console/operator/operator.go | 121 +++++------ pkg/console/operator/sync_v400.go | 125 +++++++++++ pkg/console/starter/starter.go | 19 +- .../subresource/configmap/configmap.go | 143 +++++++++++++ .../subresource/deployment/deployment.go | 195 ++++++++++++++++++ .../subresource/oauthclient/oauthclient.go | 100 +++++++++ pkg/console/subresource/route/route.go | 63 ++++++ pkg/console/subresource/secret/secret.go | 23 +++ pkg/console/subresource/service/service.go | 50 +++++ pkg/console/subresource/util/util.go | 82 ++++++++ pkg/controller/api.go | 20 ++ pkg/crypto/random.go | 36 ++++ 15 files changed, 912 insertions(+), 81 deletions(-) create mode 100644 pkg/console/operator/sync_v400.go create mode 100644 pkg/console/subresource/configmap/configmap.go create mode 100644 pkg/console/subresource/deployment/deployment.go create mode 100644 pkg/console/subresource/oauthclient/oauthclient.go create mode 100644 pkg/console/subresource/route/route.go create mode 100644 pkg/console/subresource/secret/secret.go create mode 100644 pkg/console/subresource/service/service.go create mode 100644 pkg/console/subresource/util/util.go create mode 100644 pkg/controller/api.go create mode 100644 pkg/crypto/random.go diff --git a/README.md b/README.md index 973ee1a..a9b2c12 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,11 @@ The console operator is installed by default and will automatically maintain a c * Install Go -- https://golang.org/doc/install + + + ## Development on a < 4.0.0 cluster If using `oc cluster up` on a `< 4.0.0` cluster you will need the `--public-hostname` flag diff --git a/examples/cr.yaml b/examples/cr.yaml index b8ed6fe..2957d22 100644 --- a/examples/cr.yaml +++ b/examples/cr.yaml @@ -5,7 +5,7 @@ apiVersion: "console.openshift.io/v1alpha1" kind: "Console" metadata: # Do not change the name, the operator explicitly requires this name to match as the console is a singleton. - name: openshift-console + name: console-operator-resource namespace: openshift-console spec: # openshift/api/operator/v1alpha1/types.go @@ -15,6 +15,11 @@ spec: # - Removed indicates that the operator should delete all of the sub-resources of the console managementState: Managed # there should be only one console at this time + # this could be used to support leader election if desired count: 1 logging: level: 0 + # artifact of base operator + version: 4.0.0 + # going away + value: "panda-bears-are-awesome-and-this-should-be-a-console-instead-woot" diff --git a/pkg/apis/console/v1alpha1/types.go b/pkg/apis/console/v1alpha1/types.go index 24ee950..20f0dc2 100644 --- a/pkg/apis/console/v1alpha1/types.go +++ b/pkg/apis/console/v1alpha1/types.go @@ -19,8 +19,10 @@ type Console struct { type ConsoleSpec struct { v1alpha1.OperatorSpec - + // TODO: delete this, its no longer needed Value string `json:"value,omitempty"` + // Count is the number of Console replicas + Count int32 `json:"count,omitempty"` } type ConsoleStatus struct { diff --git a/pkg/console/operator/operator.go b/pkg/console/operator/operator.go index 286eb42..2ae3be3 100644 --- a/pkg/console/operator/operator.go +++ b/pkg/console/operator/operator.go @@ -2,63 +2,44 @@ package operator import ( "fmt" + "github.com/openshift/console-operator/pkg/controller" "github.com/blang/semver" - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/informers/core/v1" - coreclientv1 "k8s.io/client-go/kubernetes/typed/core/v1" appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1" + coreclientv1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" operatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1" - "github.com/openshift/library-go/pkg/operator/resource/resourceapply" + oauthclientv1 "github.com/openshift/client-go/oauth/clientset/versioned/typed/oauth/v1" + oauthinformersv1 "github.com/openshift/client-go/oauth/informers/externalversions/oauth/v1" + routeclientv1 "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1" "github.com/openshift/library-go/pkg/operator/versioning" // informers routesinformersv1 "github.com/openshift/client-go/route/informers/externalversions/route/v1" - appsinformersv1 "k8s.io/client-go/informers/apps/v1" - oauthinformersv1 "github.com/openshift/client-go/oauth/informers/externalversions/oauth/v1" + consolev1alpha1 "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" consoleinformers "github.com/openshift/console-operator/pkg/generated/informers/externalversions/console/v1alpha1" + appsinformersv1 "k8s.io/client-go/informers/apps/v1" // clients "github.com/openshift/console-operator/pkg/generated/clientset/versioned/typed/console/v1alpha1" - routeclientv1 "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1" - oauthclientv1 "github.com/openshift/client-go/oauth/clientset/versioned/typed/oauth/v1" - // operator - "github.com/openshift/console-operator/pkg/controller" - consolev1alpha1 "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" ) const ( - // TargetNamespace could be made configurable if desired - TargetNamespace = "openshift-console" - - // ResourceName could be made configurable if desired - // all resources share the same name to make it easier to reason about and to configure single item watches - // NOTE: this must match metadata.name in the CR.yaml else the CR will be ignored - ResourceName = "console-operator-resource" - // workQueueKey is the singleton key shared by all events // the value is irrelevant workQueueKey = "console-operator-queue-key" + controllerName = "Console" ) -// consts to maintain existing names of various sub-resources -const ( - OpenShiftConsoleName = "openshift-console" - OpenShiftConsoleShortName = "console" - OpenShiftConsoleNamespace = "openshift-console" -) -// func NewConsoleOperator( -// coi consoleinformers.ConsoleOperatorInformer, -// si v1.SecretInformer, -// operatorClient v1alpha1.ConsoleOperatorInterface, -// secretsClient coreclientv1.SecretsGetter) *ConsoleOperator { +// the ConsoleOperator uses specific, strongly-typed clients +// for each resource that it interacts with. func NewConsoleOperator( // informers coi consoleinformers.ConsoleInformer, @@ -98,7 +79,7 @@ func NewConsoleOperator( // we do not really need to wait for our informers to sync since we only watch a single resource // and make live reads but it does not hurt anything and guarantees we have the correct behavior internalController, queue := controller.New( - "Console", + controllerName, c.sync, operatorInformer.HasSynced, secretsInformer.HasSynced, @@ -158,11 +139,12 @@ func (c *ConsoleOperator) Run(stopCh <-chan struct{}) { // sync() is the handler() function equivalent from the sdk // this is the big switch statement. +// TODO: clean this up a bit, its messy func (c *ConsoleOperator) sync(_ interface{}) error { // we ignore the passed in key because it will always be workQueueKey // it does not matter how the sync loop was triggered // all we need to worry about is reconciling the state back to what we expect - operatorConfig, err := c.operatorClient.Get(ResourceName, metav1.GetOptions{}) + operatorConfig, err := c.operatorClient.Get(controller.ResourceName, metav1.GetOptions{}) if errors.IsNotFound(err) { _, err := c.operatorClient.Create(c.defaultConsole()) @@ -178,7 +160,7 @@ func (c *ConsoleOperator) sync(_ interface{}) error { case operatorsv1alpha1.Unmanaged: return nil case operatorsv1alpha1.Removed: - return utilerrors.FilterOut(c.secretsClient.Secrets(TargetNamespace).Delete(ResourceName, nil), errors.IsNotFound) + return utilerrors.FilterOut(c.secretsClient.Secrets(controller.TargetNamespace).Delete(controller.ResourceName, nil), errors.IsNotFound) default: // TODO should update status return fmt.Errorf("unknown state: %v", operatorConfig.Spec.ManagementState) @@ -200,49 +182,48 @@ func (c *ConsoleOperator) sync(_ interface{}) error { // TODO report failing status, we may actually attempt to do this in the "normal" error handling return err } - v310_00_to_unknown := versioning.NewRangeOrDie("3.10.0", "3.10.1") + + // v310_00_to_unknown := versioning.NewRangeOrDie("3.10.0", "3.10.1") + v400 := versioning.NewRangeOrDie("4.0.0", "4.0.0") outConfig := operatorConfig.DeepCopy() var errs []error - - fmt.Println("[Version]") - fmt.Printf("Current version: %v, Desired version: %v \n", currentActualVerion, desiredVersion) - fmt.Printf("Between or empty? %v, between? %v", v310_00_to_unknown.BetweenOrEmpty(currentActualVerion), v310_00_to_unknown.Between(&desiredVersion)) - fmt.Println("-------------") - switch { - // TODO: - // Essentially currentActualVersion & desiredVersion matches - // our current version is so it triggers this block. - // once we put a version (4.0.0) it will no longer trigger this block. - // we need an actual v4 - // so - // case is_v400 - // reconcile v400 - // case is_v311_but_upgrading - // upgrade v400 - // etc. - case v310_00_to_unknown.BetweenOrEmpty(currentActualVerion) && v310_00_to_unknown.Between(&desiredVersion): - _, _, err := resourceapply.ApplySecret(c.secretsClient, &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: ResourceName, - Namespace: TargetNamespace, - }, - Data: map[string][]byte{ - operatorConfig.Spec.Value: []byte("007"), - }, - }) - errs = append(errs, err) - - if err == nil { // this needs work, but good enough for now - outConfig.Status.TaskSummary = "sync-[3.10.0,3.10.1)" - outConfig.Status.CurrentAvailability = &operatorsv1alpha1.VersionAvailability{ - Version: desiredVersion.String(), - } + // v4.0.0 or nil + case v400.BetweenOrEmpty(currentActualVerion): + fmt.Println("--- must be a 4.0.0") + sync_v400(c, operatorConfig) + // errs = append(errs, err) + // if err == nil { + outConfig.Status.TaskSummary = "sync-4.0.0" + outConfig.Status.CurrentAvailability = &operatorsv1alpha1.VersionAvailability{ + Version: desiredVersion.String(), } + //case v310_00_to_unknown.BetweenOrEmpty(currentActualVerion) && v310_00_to_unknown.Between(&desiredVersion): + // fmt.Println("---- v310_00_to_stuff") + // + // _, _, err := resourceapply.ApplySecret(c.secretsClient, &corev1.Secret{ + // ObjectMeta: metav1.ObjectMeta{ + // Name: ResourceName, + // Namespace: TargetNamespace, + // }, + // Data: map[string][]byte{ + // operatorConfig.Spec.Value: []byte("007"), + // }, + // }) + // errs = append(errs, err) + // + // if err == nil { // this needs work, but good enough for now + // outConfig.Status.TaskSummary = "sync-[3.10.0,3.10.1)" + // outConfig.Status.CurrentAvailability = &operatorsv1alpha1.VersionAvailability{ + // Version: desiredVersion.String(), + // } + // } + default: + fmt.Println("Unrecognized version") outConfig.Status.TaskSummary = "unrecognized" } @@ -257,13 +238,13 @@ func (c *ConsoleOperator) sync(_ interface{}) error { func (c *ConsoleOperator) defaultConsole() *consolev1alpha1.Console { return &consolev1alpha1.Console{ ObjectMeta: metav1.ObjectMeta{ - // Name: OpenShiftConsoleName, - Name: ResourceName, - Namespace: OpenShiftConsoleNamespace, + Name: controller.ResourceName, + Namespace: controller.OpenShiftConsoleNamespace, }, Spec: consolev1alpha1.ConsoleSpec{ OperatorSpec: operatorsv1alpha1.OperatorSpec{ ManagementState: "Managed", + Version: "4.0.0", }, }, } diff --git a/pkg/console/operator/sync_v400.go b/pkg/console/operator/sync_v400.go new file mode 100644 index 0000000..ef26469 --- /dev/null +++ b/pkg/console/operator/sync_v400.go @@ -0,0 +1,125 @@ +package operator + +import ( + v1alpha12 "github.com/openshift/api/operator/v1alpha1" + "github.com/openshift/console-operator/pkg/console/subresource/secret" + "github.com/openshift/console-operator/pkg/crypto" + "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" + // kube + apierrors "k8s.io/apimachinery/pkg/api/errors" + errutil "k8s.io/apimachinery/pkg/util/errors" + // openshift + "github.com/openshift/library-go/pkg/operator/resource/resourceapply" + // operator + "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" + servicesub "github.com/openshift/console-operator/pkg/console/subresource/service" + configmapsub "github.com/openshift/console-operator/pkg/console/subresource/configmap" + deploymentsub "github.com/openshift/console-operator/pkg/console/subresource/deployment" + oauthsub "github.com/openshift/console-operator/pkg/console/subresource/oauthclient" + routesub "github.com/openshift/console-operator/pkg/console/subresource/route" + +) + +// runs the standard v4.0.0 reconcile loop +func sync_v400(co *ConsoleOperator, console *v1alpha1.Console) error { + // aggregate the errors from this: + allErrors := []error{} + toUpdate := false + + + // apply service + _, svcChanged, err := resourceapply.ApplyService(co.serviceClient, servicesub.DefaultService(console)) + if err != nil { + allErrors = append(allErrors, err) + } + toUpdate = toUpdate || svcChanged + + + // apply route + rt, rtChanged, err := routesub.ApplyRoute(co.routeClient, routesub.DefaultRoute(console)) + + if err != nil { + allErrors = append(allErrors, err) + } + toUpdate = toUpdate || rtChanged + + + // apply configmap (needs route) + _, cmChanged, err := resourceapply.ApplyConfigMap(co.configMapClient, configmapsub.DefaultConfigMap(console, rt)) + if err != nil { + allErrors = append(allErrors, err) + } + toUpdate = toUpdate || cmChanged + + + // apply deployment is a bit more involved as it needs information about version & if we should + // force a rollout of the pods. at this point, configMap updates are the bool for this + defaultDeployment := deploymentsub.DefaultDeployment(console) + versionAvailability := &v1alpha12.VersionAvailability{ + Version: console.Spec.Version, + } + deploymentGeneration := resourcemerge.ExpectedDeploymentGeneration(defaultDeployment, versionAvailability) + redeployPods := cmChanged + _, dpChanged, err := resourceapply.ApplyDeployment(co.deploymentClient, defaultDeployment, deploymentGeneration, redeployPods) + if err != nil { + allErrors = append(allErrors, err) + } + toUpdate = toUpdate || dpChanged + + + // shared + sharedOAuthSecretBits := crypto.Random256BitsString() + + + // apply oauth (needs route) + defaultOauthClient := oauthsub.RegisterConsoleToOAuthClient(oauthsub.DefaultOauthClient(), rt, sharedOAuthSecretBits) + _, oauthChanged, err := oauthsub.ApplyOAuth(co.oauthClient, defaultOauthClient) + if err != nil { + allErrors = append(allErrors, err) + } + toUpdate = toUpdate || oauthChanged + + + // apply secret + _, secretChanged, err := resourceapply.ApplySecret(co.secretsClient, secret.DefaultSecret(console,sharedOAuthSecretBits)) + if err != nil { + allErrors = append(allErrors, err) + } + toUpdate = toUpdate || secretChanged + + + // if any of our resources have svcChanged, we should update the CR. otherwise, skip this step. + if toUpdate { + // update status on CR + // pass in each of the above resources, possibly the + // boolean for "changed" as well, and then assign a status + // on the CR.Status. Be sure to account for a nil return value + // as some of our resources (oauthlient, configmap) may simply + // not be possible to create if they lack the appropriate inputs. + // in this case, the Status should CLEARLY indicate this to the user. + // Once the resource is correctly created, the status should be updated + // again. This should be pretty simple and straightforward work. + // update cluster operator status... i believe this + // should be automatic so long as the CR.Status is + // properly filled out with the appropriate values. + } + + return errutil.FilterOut(errutil.NewAggregate(allErrors), apierrors.IsNotFound) +} + + +//func DeleteAllResources(cr *v1alpha1.Console) error { +// var errs []error +// for _, fn := range []func(*v1alpha1.Console) error{ +// DeleteService, +// DeleteRoute, +// DeleteConfigMap, +// DeleteDeployment, +// DeleteOAuthSecret, +// // we don't own it and can't create or delete it. however, we can update it +// NeutralizeOAuthClient, +// } { +// errs = append(errs, fn(cr)) +// } +// return errutil.FilterOut(errutil.NewAggregate(errs), errors.IsNotFound) +//} diff --git a/pkg/console/starter/starter.go b/pkg/console/starter/starter.go index 25bfdb9..8a2947f 100644 --- a/pkg/console/starter/starter.go +++ b/pkg/console/starter/starter.go @@ -2,10 +2,11 @@ package starter import ( "fmt" + "github.com/openshift/console-operator/pkg/controller" "time" - "k8s.io/client-go/tools/cache" "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/cache" // "k8s.io/apimachinery/pkg/fields" "k8s.io/client-go/dynamic" "k8s.io/client-go/informers" @@ -14,9 +15,9 @@ import ( "github.com/openshift/library-go/pkg/operator/status" + authclient "github.com/openshift/client-go/oauth/clientset/versioned" // clients routesclient "github.com/openshift/client-go/route/clientset/versioned" - authclient "github.com/openshift/client-go/oauth/clientset/versioned" "github.com/openshift/console-operator/pkg/generated/clientset/versioned" // informers oauthinformers "github.com/openshift/client-go/oauth/informers/externalversions" @@ -78,7 +79,7 @@ func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { resync, // takes an unlimited number of additional "options" arguments, which are functions, // that take a sharedInformerFactory and return a sharedInformerFactory - informers.WithNamespace(operator.TargetNamespace), + informers.WithNamespace(controller.TargetNamespace), informers.WithTweakListOptions(tweakListOptions), ) @@ -87,14 +88,14 @@ func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { consoleOperatorClient, resync, // and the same set of optional transform functions - externalversions.WithNamespace(operator.TargetNamespace), + externalversions.WithNamespace(controller.TargetNamespace), externalversions.WithTweakListOptions(tweakListOptions), ) routesInformersNamespaced := routesinformers.NewSharedInformerFactoryWithOptions( routesClient, resync, - routesinformers.WithNamespace(operator.TargetNamespace), + routesinformers.WithNamespace(controller.TargetNamespace), routesinformers.WithTweakListOptions(tweakListOptions), ) @@ -113,7 +114,7 @@ func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { routesInformersNamespaced.Route().V1(), // Route oauthInformers.Oauth().V1(), // oauth // clients - consoleOperatorClient.ConsoleV1alpha1().Consoles(operator.TargetNamespace), + consoleOperatorClient.ConsoleV1alpha1().Consoles(controller.TargetNamespace), kubeClient.CoreV1(), // Secrets, ConfigMaps, Service kubeClient.AppsV1(), routesClient.RouteV1(), @@ -129,8 +130,8 @@ func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { clusterOperatorStatus := status.NewClusterOperatorStatusController( - operator.TargetNamespace, - operator.ResourceName, + controller.TargetNamespace, + controller.ResourceName, // no idea why this is dynamic & not a strongly typed client. dynamicClient, &operatorStatusProvider{informers: consoleOperatorInformers}, @@ -154,7 +155,7 @@ func (p *operatorStatusProvider) Informer() cache.SharedIndexInformer { } func (p *operatorStatusProvider) CurrentStatus() (operatorv1alpha1.OperatorStatus, error) { - instance, err := p.informers.Console().V1alpha1().Consoles().Lister().Consoles(operator.TargetNamespace).Get(operator.ResourceName) + instance, err := p.informers.Console().V1alpha1().Consoles().Lister().Consoles(controller.TargetNamespace).Get(controller.ResourceName) if err != nil { return operatorv1alpha1.OperatorStatus{}, err } diff --git a/pkg/console/subresource/configmap/configmap.go b/pkg/console/subresource/configmap/configmap.go new file mode 100644 index 0000000..ab1afb5 --- /dev/null +++ b/pkg/console/subresource/configmap/configmap.go @@ -0,0 +1,143 @@ +package configmap + +import ( + "fmt" + "github.com/openshift/api/route/v1" + "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" + "github.com/openshift/console-operator/pkg/console/subresource/util" + "github.com/openshift/console-operator/pkg/controller" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v2" + corev1 "k8s.io/api/core/v1" +) + +const ( + ConsoleConfigMapName = "console-config" + consoleConfigYamlFile = "console-config.yaml" + clientSecretFilePath = "/var/oauth-config/clientSecret" + oauthEndpointCAFilePath = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" + // TODO: should this be configurable? likely so. + documentationBaseURL = "https://docs.okd.io/4.0/" + brandingDefault = "okd" + // serving info + certFilePath = "/var/serving-cert/tls.crt" + keyFilePath = "/var/serving-cert/tls.key" +) + +func DefaultConfigMap(cr *v1alpha1.Console, rt *v1.Route) *corev1.ConfigMap { + if rt == nil { + // without a route, the configmap is useless. + // we should log, set the CR.status, and possibly create an Event + // if we can't create this. Its a big deal. + // (and update again once it's working) + // also, maybe we do get a route, but if it has no host, + // default or custom (or both or neither) then we need to + // handle cr.Status on that as well. That can be done + // in context of route, not here. + return nil + } + host := rt.Spec.Host + meta := util.SharedMeta() + meta.Name = ConsoleConfigMapName + config := NewYamlConfigString(host) + configMap := &corev1.ConfigMap{ + ObjectMeta: meta, + Data: map[string]string{ + consoleConfigYamlFile: config, + }, + } + util.AddOwnerRef(configMap, util.OwnerRefFrom(cr)) + return configMap +} + +func NewYamlConfigString(host string) string { + return string(NewYamlConfig(host)) +} + +func NewYamlConfig(host string) []byte { + conf := yaml.MapSlice{ + { + Key: "kind", Value: "ConsoleConfig", + }, { + Key: "apiVersion", Value: "console.openshift.io/v1beta1", + }, { + Key: "auth", Value: authServerYaml(), + }, { + Key: "clusterInfo", Value: clusterInfo(host), + }, { + Key: "customization", Value: customization(), + }, { + Key: "servingInfo", Value: servingInfo(), + }, + } + yml, err := yaml.Marshal(conf) + if err != nil { + fmt.Printf("Could not create config yaml %v", err) + return nil + } + return yml +} + +func servingInfo() yaml.MapSlice { + return yaml.MapSlice{ + { + Key: "bindAddress", Value: "https://0.0.0.0:8443", + }, { + Key: "certFile", Value: certFilePath, + }, { + Key: "keyFile", Value: keyFilePath, + }, + } +} + +// TODO: take args as we update branding based on cluster config? +func customization() yaml.MapSlice { + return yaml.MapSlice{ + { + Key: "branding", Value: brandingDefault, + }, { + Key: "documentationBaseURL", Value: documentationBaseURL, + }, + } +} + +//// TODO: this can take args as we update locations after we generate a router +func clusterInfo(host string) yaml.MapSlice { + return yaml.MapSlice{ + { + Key: "consoleBaseAddress", Value: consoleBaseAddr(host), + }, { + Key: "consoleBasePath", Value: "", + }, + // { + // Key: "masterPublicURL", Value: nil, + // }, + } + +} + +func authServerYaml() yaml.MapSlice { + return yaml.MapSlice{ + { + Key: "clientID", Value: controller.OpenShiftConsoleName, + // Key: "clientID", Value: OAuthClientName, + }, { + Key: "clientSecretFile", Value: clientSecretFilePath, + }, { + Key: "logoutRedirect", Value: "", + }, { + Key: "oauthEndpointCAFile", Value: oauthEndpointCAFilePath, + }, + } +} + +func consoleBaseAddr(host string) string { + if host != "" { + str := fmt.Sprintf("https://%s", host) + logrus.Infof("console configmap base addr set to %v", str) + return str + } + return "" +} + + diff --git a/pkg/console/subresource/deployment/deployment.go b/pkg/console/subresource/deployment/deployment.go new file mode 100644 index 0000000..439f362 --- /dev/null +++ b/pkg/console/subresource/deployment/deployment.go @@ -0,0 +1,195 @@ +package deployment + +import ( + "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" + "github.com/openshift/console-operator/pkg/console/subresource/util" + "github.com/openshift/console-operator/pkg/controller" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +const ( + consolePortName = "https" + consolePort = 443 + consoleTargetPort = 8443 + publicURLName = "BRIDGE_DEVELOPER_CONSOLE_URL" + ConsoleServingCertName = "console-serving-cert" + ConsoleOauthConfigName = "console-oauth-config" +) + +type volumeConfig struct { + name string + readOnly bool + path string + // defaultMode int + // will be either secret or configMap + isSecret bool + isConfigMap bool +} + +var volumeConfigList = []volumeConfig{ + { + name: ConsoleServingCertName, + readOnly: true, + path: "/var/serving-cert", + isSecret: true, + // defaultMode: 288, + }, + { + name: ConsoleOauthConfigName, + readOnly: true, + path: "/var/oauth-config", + isSecret: true, + // defaultMode: 288, + }, + { + name: "console-config", + readOnly: true, + path: "/var/console-config", + isConfigMap: true, + // defaultMode: 288, + }, +} + +func DefaultDeployment(cr *v1alpha1.Console) *appsv1.Deployment { + labels := util.LabelsForConsole() + meta := util.SharedMeta() + meta.Labels = labels + replicas := cr.Spec.Count + gracePeriod := int64(30) + + deployment := &appsv1.Deployment{ + ObjectMeta: meta, + Spec: appsv1.DeploymentSpec{ + Replicas: &replicas, + Selector: &metav1.LabelSelector{ + MatchLabels: labels, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Name: controller.OpenShiftConsoleShortName, + Labels: labels, + Annotations: map[string]string{}, + }, + Spec: corev1.PodSpec{ + // TODO: NodeSelector: corev1.NodeSelector{}, + RestartPolicy: corev1.RestartPolicyAlways, + SchedulerName: corev1.DefaultSchedulerName, + TerminationGracePeriodSeconds: &gracePeriod, + SecurityContext: &corev1.PodSecurityContext{}, + Containers: []corev1.Container{ + consoleContainer(cr), + }, + Volumes: consoleVolumes(volumeConfigList), + }, + }, + }, + } + util.AddOwnerRef(deployment, util.OwnerRefFrom(cr)) + return deployment +} + +// deduplication, use the same volume config to generate Volumes, and VolumeMounts +func consoleVolumes(vc []volumeConfig) []corev1.Volume { + vols := make([]corev1.Volume, len(vc)) + for i, item := range vc { + if item.isSecret { + vols[i] = corev1.Volume{ + Name: item.name, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: item.name, + }, + }, + } + } + if item.isConfigMap { + vols[i] = corev1.Volume{ + Name: item.name, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: item.name, + }, + }, + }, + } + } + } + return vols +} + +func consoleVolumeMounts(vc []volumeConfig) []corev1.VolumeMount { + volMountList := make([]corev1.VolumeMount, len(vc)) + for i, item := range vc { + volMountList[i] = corev1.VolumeMount{ + Name: item.name, + ReadOnly: item.readOnly, + MountPath: item.path, + } + } + return volMountList +} + +func consoleContainer(cr *v1alpha1.Console) corev1.Container { + volumeMounts := consoleVolumeMounts(volumeConfigList) + + return corev1.Container{ + Image: util.GetImageEnv(), + ImagePullPolicy: corev1.PullPolicy("IfNotPresent"), + Name: controller.OpenShiftConsoleShortName, + Command: []string{ + "/opt/bridge/bin/bridge", + "--public-dir=/opt/bridge/static", + "--config=/var/console-config/console-config.yaml", + }, + // TODO: can probably remove, this is used for local dev + //Env: []corev1.EnvVar{{ + // Name: publicURLName, + // Value: consoleURL(), + //}}, + Ports: []corev1.ContainerPort{{ + Name: consolePortName, + Protocol: corev1.ProtocolTCP, + ContainerPort: consolePort, + }}, + VolumeMounts: volumeMounts, + ReadinessProbe: defaultProbe(), + LivenessProbe: livenessProbe(), + TerminationMessagePath: "/dev/termination-log", + TerminationMessagePolicy: corev1.TerminationMessagePolicy("File"), + Resources: corev1.ResourceRequirements{ + Limits: map[corev1.ResourceName]resource.Quantity{ + // TODO: fill these out + // "cpu": int64(100), + // "memory": int64(100) + }, + Requests: map[corev1.ResourceName]resource.Quantity{}, + }, + } +} + +func defaultProbe() *corev1.Probe { + return &corev1.Probe{ + Handler: corev1.Handler{ + HTTPGet: &corev1.HTTPGetAction{ + Path: "/health", + Port: intstr.FromInt(8443), + Scheme: corev1.URIScheme("HTTPS"), + }, + }, + TimeoutSeconds: 1, + PeriodSeconds: 10, + SuccessThreshold: 1, + FailureThreshold: 3, + } +} + +func livenessProbe() *corev1.Probe { + probe := defaultProbe() + probe.InitialDelaySeconds = 30 + return probe +} diff --git a/pkg/console/subresource/oauthclient/oauthclient.go b/pkg/console/subresource/oauthclient/oauthclient.go new file mode 100644 index 0000000..efb7ee7 --- /dev/null +++ b/pkg/console/subresource/oauthclient/oauthclient.go @@ -0,0 +1,100 @@ +package oauthclient + +import ( + "fmt" + oauthv1 "github.com/openshift/api/oauth/v1" + "github.com/openshift/api/route/v1" + oauthclient "github.com/openshift/client-go/oauth/clientset/versioned/typed/oauth/v1" + "github.com/openshift/console-operator/pkg/controller" + "github.com/openshift/console-operator/pkg/crypto" + "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" + "github.com/sirupsen/logrus" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "strings" +) + +// TODO: ApplyOauth should be a generic Apply that could be used for any oauth-client +// - should look like resourceapply.ApplyService +// - perhaps should be PR'd to client-go +func ApplyOAuth(client oauthclient.OAuthClientsGetter, required *oauthv1.OAuthClient) (*oauthv1.OAuthClient, bool, error) { + existing, err := client.OAuthClients().Get(required.Name, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + actual, err := client.OAuthClients().Create(required) + return actual, true, err + } + if err != nil { + return nil, false, err + } + // Unfortunately data is all top level so its a little more + // tedious to manually copy things over + modified := resourcemerge.BoolPtr(false) + resourcemerge.EnsureObjectMeta(modified, &existing.ObjectMeta, required.ObjectMeta) + existing.Secret = required.Secret + existing.AdditionalSecrets = required.AdditionalSecrets + existing.RespondWithChallenges = required.RespondWithChallenges + existing.RedirectURIs = required.RedirectURIs + existing.GrantMethod = required.GrantMethod + existing.ScopeRestrictions = required.ScopeRestrictions + existing.AccessTokenMaxAgeSeconds = required.AccessTokenMaxAgeSeconds + existing.AccessTokenInactivityTimeoutSeconds = required.AccessTokenInactivityTimeoutSeconds + + actual, err := client.OAuthClients().Update(existing) + return actual, true, err +} + +// registers the console on the oauth client as a valid application +func RegisterConsoleToOAuthClient(client *oauthv1.OAuthClient, route *v1.Route, randomBits string) *oauthv1.OAuthClient { + // without a route, we cannot create a usable oauth client + if route == nil { + return nil + } + // we should be the only ones using this client, so we can + // stomp all over existing RedirectURIs. + // TODO: potentially support multiple if multiple routes service + // the console + client.RedirectURIs = []string{} + client.RedirectURIs = append(client.RedirectURIs, https(route.Spec.Host)) + client.Secret = randomBits + return client +} + +// for ManagementState.Removed +func DeRegisterConsoleFromOAuthClient(client *oauthv1.OAuthClient) *oauthv1.OAuthClient { + client.RedirectURIs = []string{} + // changing the string to anything else will invalidate the client + client.Secret = crypto.Random256BitsString() + return client +} + +// cr *v1alpha1.Console, rt *v1.Route +// the OAuthClient is a cluster scoped resource that will be stamped +// out on install by the CVO. We know for certain we will not create +// this, so there is no point in fleshing out its values here, unlike +// the other resources we are responsible for. +func DefaultOauthClient() *oauthv1.OAuthClient{ + // we cannot set an ownerRef on the OAuthClient as it is + // a cluster scoped resource. + return &oauthv1.OAuthClient{ + ObjectMeta: metav1.ObjectMeta{ + Name: controller.OpenShiftConsoleName, + }, + // we can't really set these here yet but need them + // RedirectURIs: []string{}, + // Secret: crypto.Random256BitsString(), + } +} + +func https(host string) string { + protocol := "https://" + if host == "" { + logrus.Infof("host is invalid empty string") + return "" + } + if strings.HasPrefix(host, protocol) { + return host + } + secured := fmt.Sprintf("%s%s", protocol, host) + logrus.Infof("host updated from %s to %s", host, secured) + return secured +} diff --git a/pkg/console/subresource/route/route.go b/pkg/console/subresource/route/route.go new file mode 100644 index 0000000..8fcf08a --- /dev/null +++ b/pkg/console/subresource/route/route.go @@ -0,0 +1,63 @@ +package route + +import ( + routev1 "github.com/openshift/api/route/v1" + routeclient "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1" + "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" + "github.com/openshift/console-operator/pkg/console/subresource/util" + "github.com/openshift/console-operator/pkg/controller" + "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +// TODO: ApplyRoute +// - should look like resourceapply.ApplyService +// - should be PR'd to client-go +func ApplyRoute(client routeclient.RoutesGetter, required *routev1.Route) (*routev1.Route, bool, error) { + // first, get or create + existing, err := client.Routes(required.Namespace).Get(required.Name, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + actual, err := client.Routes(required.Namespace).Create(required) + return actual, true, err + } + if err != nil { + return nil, false, err + } + // otherwise update + modified := resourcemerge.BoolPtr(false) + resourcemerge.EnsureObjectMeta(modified, &existing.ObjectMeta, required.ObjectMeta) + + toWrite := existing + toWrite.Spec = *required.Spec.DeepCopy() + + actual, err := client.Routes(required.Namespace).Update(toWrite) + return actual, true, err +} + +func DefaultRoute(cr *v1alpha1.Console) *routev1.Route { + meta := util.SharedMeta() + meta.Name = controller.OpenShiftConsoleShortName + weight := int32(100) + route := &routev1.Route{ + ObjectMeta: meta, + Spec: routev1.RouteSpec{ + To: routev1.RouteTargetReference{ + Kind: "Service", + Name: meta.Name, + Weight: &weight, + }, + Port: &routev1.RoutePort{ + TargetPort: intstr.FromString("https"), + }, + TLS: &routev1.TLSConfig{ + Termination: routev1.TLSTerminationReencrypt, + InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect, + }, + WildcardPolicy: routev1.WildcardPolicyNone, + }, + } + util.AddOwnerRef(route, util.OwnerRefFrom(cr)) + return route +} diff --git a/pkg/console/subresource/secret/secret.go b/pkg/console/subresource/secret/secret.go new file mode 100644 index 0000000..1495217 --- /dev/null +++ b/pkg/console/subresource/secret/secret.go @@ -0,0 +1,23 @@ +package secret + +import ( + "k8s.io/api/core/v1" + "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" + "github.com/openshift/console-operator/pkg/console/subresource/deployment" + "github.com/openshift/console-operator/pkg/console/subresource/util" +) + +const dataKey = "clientsecret" + +func DefaultSecret(cr *v1alpha1.Console, randomBits string) *v1.Secret { + meta := util.SharedMeta() + meta.Name = deployment.ConsoleOauthConfigName + secret := &v1.Secret{ + ObjectMeta: meta, + } + secret.StringData = map[string]string{ + dataKey: randomBits, + } + util.AddOwnerRef(secret, util.OwnerRefFrom(cr)) + return secret +} diff --git a/pkg/console/subresource/service/service.go b/pkg/console/subresource/service/service.go new file mode 100644 index 0000000..9654f18 --- /dev/null +++ b/pkg/console/subresource/service/service.go @@ -0,0 +1,50 @@ +package service + +import ( + "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" + "github.com/openshift/console-operator/pkg/console/subresource/util" + "github.com/openshift/console-operator/pkg/controller" + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +const ( + // this annotation should generate us a certificate + ServingCertSecretAnnotation = "service.alpha.openshift.io/serving-cert-secret-name" +) + +const ( + // perhaps move + ConsoleServingCertName = "console-serving-cert" + consolePortName = "https" + consolePort = 443 + consoleTargetPort = 8443 +) + +func DefaultService(cr *v1alpha1.Console) *v1.Service { + labels := util.LabelsForConsole() + meta := util.SharedMeta() + meta.Name = controller.OpenShiftConsoleShortName + meta.Annotations = map[string]string{ + ServingCertSecretAnnotation: ConsoleServingCertName, + } + service := &v1.Service{ + ObjectMeta: meta, + Spec: v1.ServiceSpec{ + Ports: []v1.ServicePort{ + { + Name: consolePortName, + Protocol: v1.ProtocolTCP, + Port: consolePort, + TargetPort: intstr.FromInt(consoleTargetPort), + }, + }, + Selector: labels, + Type: "ClusterIP", + SessionAffinity: "None", + }, + } + + util.AddOwnerRef(service, util.OwnerRefFrom(cr)) + return service +} diff --git a/pkg/console/subresource/util/util.go b/pkg/console/subresource/util/util.go new file mode 100644 index 0000000..913eead --- /dev/null +++ b/pkg/console/subresource/util/util.go @@ -0,0 +1,82 @@ +package util + +import ( + "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" + "github.com/openshift/console-operator/pkg/controller" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v2" + "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "os" +) + +func SharedLabels() map[string]string { + return map[string]string{ + "app": controller.OpenShiftConsoleName, + } +} + +func LabelsForConsole() map[string]string { + baseLabels := SharedLabels() + + extraLabels := map[string]string{ + "component": "ui", + } + // we want to deduplicate, so doing these two loops. + allLabels := map[string]string{} + + for key, value := range baseLabels { + allLabels[key] = value + } + for key, value := range extraLabels { + allLabels[key] = value + } + return allLabels +} + +func SharedMeta() v1.ObjectMeta { + return v1.ObjectMeta{ + Name: controller.OpenShiftConsoleName, + Namespace: controller.OpenShiftConsoleName, + Labels: SharedLabels(), + } +} + +func LogYaml(obj runtime.Object) { + // REALLY NOISY, but handy for debugging: + // deployJSON, err := json.Marshal(d) + deployYAML, err := yaml.Marshal(obj) + if err != nil { + logrus.Info("failed to show deployment yaml in log") + } + logrus.Infof("Deploying: %v", string(deployYAML)) +} + +// objects can have more than one ownerRef, potentially +func AddOwnerRef(obj v1.Object, ownerRef *v1.OwnerReference) { + if obj != nil { + if ownerRef != nil { + obj.SetOwnerReferences(append(obj.GetOwnerReferences(), *ownerRef)) + } + } +} + +func OwnerRefFrom(cr *v1alpha1.Console) *v1.OwnerReference { + if cr != nil { + truthy := true + return &v1.OwnerReference{ + APIVersion: cr.APIVersion, + Kind: cr.Kind, + Name: cr.Name, + UID: cr.UID, + Controller: &truthy, + } + } + return nil +} + +// borrowed from library-go +// https://github.com/openshift/library-go/blob/master/pkg/operator/v1alpha1helpers/helpers.go +func GetImageEnv() string { + return os.Getenv("IMAGE") +} diff --git a/pkg/controller/api.go b/pkg/controller/api.go new file mode 100644 index 0000000..62e15e7 --- /dev/null +++ b/pkg/controller/api.go @@ -0,0 +1,20 @@ +package controller + +// atm dumping ground for consts + +const ( + // TargetNamespace could be made configurable if desired + TargetNamespace = "openshift-console" + // ResourceName could be made configurable if desired + // all resources share the same name to make it easier to reason about and to configure single item watches + // NOTE: this must match metadata.name in the CR.yaml else the CR will be ignored + ResourceName = "console-operator-resource" +) + +// consts to maintain existing names of various sub-resources +const ( + OpenShiftConsoleName = "openshift-console" + OpenShiftConsoleShortName = "console" + OpenShiftConsoleNamespace = "openshift-console" +) + diff --git a/pkg/crypto/random.go b/pkg/crypto/random.go new file mode 100644 index 0000000..7375601 --- /dev/null +++ b/pkg/crypto/random.go @@ -0,0 +1,36 @@ +// From @enj openshift/origin +// https://github.com/openshift/origin/tree/9a8a2fb3f9485bf88ebea61e4b5d8bf04dd3c459/pkg/oauthserver/server/crypto +package crypto + +import ( + "crypto/rand" + "encoding/base64" +) + +// RandomBits returns a random byte slice with at least the requested bits of entropy. +// Callers should avoid using a value less than 256 unless they have a very good reason. +func RandomBits(bits int) []byte { + size := bits / 8 + if bits%8 != 0 { + size++ + } + b := make([]byte, size) + if _, err := rand.Read(b); err != nil { + panic(err) // rand should never fail + } + return b +} + +// RandomBitsString returns a random string with at least the requested bits of entropy. +// It uses RawURLEncoding to ensure we do not get / characters or trailing ='s. +func RandomBitsString(bits int) string { + return base64.RawURLEncoding.EncodeToString(RandomBits(bits)) +} + +// Random256BitsString is a convenience function for calling RandomBitsString(256). +// Callers that need a random string should use this function unless they have a +// very good reason to need a different amount of entropy. +func Random256BitsString() string { + // 32 bytes (256 bits) = 43 base64-encoded characters + return RandomBitsString(256) +} From ff8d7e487ced2bea794ebd3f19d24f77856822d2 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Mon, 19 Nov 2018 10:47:08 -0500 Subject: [PATCH 18/24] Add dev_* scripts for convenience --- dev_deploy_all.sh | 3 +++ dev_run_local.sh | 13 ++++++++++++- dev_test_sync_loop.sh | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100755 dev_test_sync_loop.sh diff --git a/dev_deploy_all.sh b/dev_deploy_all.sh index 703c5eb..3b93b97 100755 --- a/dev_deploy_all.sh +++ b/dev_deploy_all.sh @@ -5,6 +5,9 @@ # in the end, it creates a custom resource to kick # the operator into action +echo "DEPLOYING REMOTE OPERATOR" +echo "(This does not build locally, nor does it push the image to dockerhub...)" + for FILE in `find ./manifests -name '00-*'` do echo "creating ${FILE}" diff --git a/dev_run_local.sh b/dev_run_local.sh index b336fd1..be800d1 100755 --- a/dev_run_local.sh +++ b/dev_run_local.sh @@ -33,6 +33,11 @@ done sleep 2 +# use the openshift-console project, for +# - when we create the CR (namespace: should be defined in the resource anyway) +# - when we run the operator locally. +oc project 'openshift-console' + for FILE in `find ./manifests -name '02-*'` do echo "creating ${FILE}" @@ -71,6 +76,10 @@ make build # echo "creating ${FILE}" # oc create -f $FILE #done + +# temporaily add the binary to path so we can call it below +export PATH="$PATH:$HOME/gopaths/consoleoperator/src/github.com/openshift/console-operator/_output/local/bin/darwin/amd64" + IMAGE=docker.io/openshift/origin-console:latest \ console operator \ --kubeconfig $HOME/.kube/config \ @@ -78,7 +87,6 @@ IMAGE=docker.io/openshift/origin-console:latest \ --v 4 echo "TODO: support --create-default-console again!" - # TODO: GET BACK TO THIS: #IMAGE=docker.io/openshift/origin-console:latest \ # console operator \ @@ -87,4 +95,7 @@ echo "TODO: support --create-default-console again!" # --create-default-console \ # --v 4 +# NOT creating the CR as the operator should create one automatically. +# echo "Creating the CR to activate the operator" +# oc create -f "./examples/cr.yaml" diff --git a/dev_test_sync_loop.sh b/dev_test_sync_loop.sh new file mode 100755 index 0000000..04e6735 --- /dev/null +++ b/dev_test_sync_loop.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +# simply create one of each resource, with a sleep in between +# watch the logs and verify that the sync loop sees the events +# then delete each of the resources. +# these are generic resources, not specific. + +declare -a FILES_ARRAY=("secret.yaml" + "configmap.yaml" + "service.yaml" + "route.yaml" + "deployment.yaml" + "oauth.yaml" +) + +# create them all +for FILE in "${FILES_ARRAY[@]}" +do + echo "creating ${FILE}" + oc create -f "./examples/sync-loop/${FILE}" + sleep 3 +done + +# then, delete them all. + + +for FILE in "${FILES_ARRAY[@]}" +do + echo "deleting ${FILE}" + oc delete -f "./examples/sync-loop/${FILE}" + sleep 3 +done From 584f8ad85559f257853318ec477a7e08d317d2d6 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Mon, 19 Nov 2018 10:47:46 -0500 Subject: [PATCH 19/24] Add TODO to types.go to describe future custom host work --- pkg/apis/console/v1alpha1/types.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/apis/console/v1alpha1/types.go b/pkg/apis/console/v1alpha1/types.go index 20f0dc2..72149b6 100644 --- a/pkg/apis/console/v1alpha1/types.go +++ b/pkg/apis/console/v1alpha1/types.go @@ -23,6 +23,11 @@ type ConsoleSpec struct { Value string `json:"value,omitempty"` // Count is the number of Console replicas Count int32 `json:"count,omitempty"` + // take a look @: + // https://github.com/openshift/cluster-image-registry-operator/blob/master/pkg/apis/imageregistry/v1alpha1/types.go#L91-L92 + // DefaultRoute: T|F + // additional routes config w/secrets + // Route[] } type ConsoleStatus struct { From efb8e65ca3f8a98e516b5ca94eabeac1b53484ce Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Mon, 19 Nov 2018 10:49:38 -0500 Subject: [PATCH 20/24] Update sync loop, tmp remove OwnerRef --- pkg/console/operator/operator.go | 49 +++++--------- pkg/console/operator/sync_v400.go | 95 +++++++++++++++++----------- pkg/console/subresource/util/util.go | 18 +++--- 3 files changed, 85 insertions(+), 77 deletions(-) diff --git a/pkg/console/operator/operator.go b/pkg/console/operator/operator.go index 2ae3be3..dc8d1f7 100644 --- a/pkg/console/operator/operator.go +++ b/pkg/console/operator/operator.go @@ -1,11 +1,12 @@ package operator import ( + // standard lib "fmt" - "github.com/openshift/console-operator/pkg/controller" - + // 3rd party "github.com/blang/semver" - + "github.com/sirupsen/logrus" + // kube "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -15,7 +16,8 @@ import ( coreclientv1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" - + // openshift + "github.com/openshift/console-operator/pkg/controller" operatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1" oauthclientv1 "github.com/openshift/client-go/oauth/clientset/versioned/typed/oauth/v1" oauthinformersv1 "github.com/openshift/client-go/oauth/informers/externalversions/oauth/v1" @@ -159,6 +161,7 @@ func (c *ConsoleOperator) sync(_ interface{}) error { // handled below case operatorsv1alpha1.Unmanaged: return nil + // take a look @ https://github.com/openshift/service-serving-cert-signer/blob/master/pkg/operator/operator.go#L86 case operatorsv1alpha1.Removed: return utilerrors.FilterOut(c.secretsClient.Secrets(controller.TargetNamespace).Delete(controller.ResourceName, nil), errors.IsNotFound) default: @@ -166,7 +169,7 @@ func (c *ConsoleOperator) sync(_ interface{}) error { return fmt.Errorf("unknown state: %v", operatorConfig.Spec.ManagementState) } - var currentActualVerion *semver.Version + var currentActualVersion *semver.Version // TODO: ca.yaml needs a version, update the v1alpha1.Console to include version field if ca := operatorConfig.Status.CurrentAvailability; ca != nil { @@ -174,25 +177,26 @@ func (c *ConsoleOperator) sync(_ interface{}) error { if err != nil { utilruntime.HandleError(err) } else { - currentActualVerion = &ver + currentActualVersion = &ver } } + // not actually using ATM desiredVersion, err := semver.Parse(operatorConfig.Spec.Version) if err != nil { // TODO report failing status, we may actually attempt to do this in the "normal" error handling return err } - // v310_00_to_unknown := versioning.NewRangeOrDie("3.10.0", "3.10.1") - v400 := versioning.NewRangeOrDie("4.0.0", "4.0.0") + // this is arbitrary, but we need a placeholder. we will have to handle versioning appropriately at some point + v311_to_401 := versioning.NewRangeOrDie("3.11.0", "4.0.1") outConfig := operatorConfig.DeepCopy() var errs []error switch { // v4.0.0 or nil - case v400.BetweenOrEmpty(currentActualVerion): - fmt.Println("--- must be a 4.0.0") + case v311_to_401.BetweenOrEmpty(currentActualVersion): + logrus.Println("Sync-4.0.0") sync_v400(c, operatorConfig) // errs = append(errs, err) // if err == nil { @@ -200,30 +204,8 @@ func (c *ConsoleOperator) sync(_ interface{}) error { outConfig.Status.CurrentAvailability = &operatorsv1alpha1.VersionAvailability{ Version: desiredVersion.String(), } - - //case v310_00_to_unknown.BetweenOrEmpty(currentActualVerion) && v310_00_to_unknown.Between(&desiredVersion): - // fmt.Println("---- v310_00_to_stuff") - // - // _, _, err := resourceapply.ApplySecret(c.secretsClient, &corev1.Secret{ - // ObjectMeta: metav1.ObjectMeta{ - // Name: ResourceName, - // Namespace: TargetNamespace, - // }, - // Data: map[string][]byte{ - // operatorConfig.Spec.Value: []byte("007"), - // }, - // }) - // errs = append(errs, err) - // - // if err == nil { // this needs work, but good enough for now - // outConfig.Status.TaskSummary = "sync-[3.10.0,3.10.1)" - // outConfig.Status.CurrentAvailability = &operatorsv1alpha1.VersionAvailability{ - // Version: desiredVersion.String(), - // } - // } - default: - fmt.Println("Unrecognized version") + logrus.Printf("Unrecognized version. Desired %s, Actual %s", desiredVersion, currentActualVersion) outConfig.Status.TaskSummary = "unrecognized" } @@ -246,6 +228,7 @@ func (c *ConsoleOperator) defaultConsole() *consolev1alpha1.Console { ManagementState: "Managed", Version: "4.0.0", }, + Count: 1, }, } } diff --git a/pkg/console/operator/sync_v400.go b/pkg/console/operator/sync_v400.go index ef26469..4318fe6 100644 --- a/pkg/console/operator/sync_v400.go +++ b/pkg/console/operator/sync_v400.go @@ -1,14 +1,19 @@ package operator import ( - v1alpha12 "github.com/openshift/api/operator/v1alpha1" - "github.com/openshift/console-operator/pkg/console/subresource/secret" - "github.com/openshift/console-operator/pkg/crypto" - "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" + "github.com/sirupsen/logrus" // kube + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" errutil "k8s.io/apimachinery/pkg/util/errors" // openshift + oauthv1 "github.com/openshift/api/oauth/v1" + operatorv1alpha1 "github.com/openshift/api/operator/v1alpha1" + routev1 "github.com/openshift/api/route/v1" + "github.com/openshift/console-operator/pkg/console/subresource/secret" + "github.com/openshift/console-operator/pkg/crypto" + "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" "github.com/openshift/library-go/pkg/operator/resource/resourceapply" // operator "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" @@ -21,75 +26,84 @@ import ( ) // runs the standard v4.0.0 reconcile loop -func sync_v400(co *ConsoleOperator, console *v1alpha1.Console) error { +func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) error { // aggregate the errors from this: allErrors := []error{} toUpdate := false // apply service - _, svcChanged, err := resourceapply.ApplyService(co.serviceClient, servicesub.DefaultService(console)) - if err != nil { - allErrors = append(allErrors, err) + svc, svcChanged, svcErr := resourceapply.ApplyService(co.serviceClient, servicesub.DefaultService(consoleConfig)) + if svcErr != nil { + logrus.Infof("service error: %v", svcErr) + allErrors = append(allErrors, svcErr) } toUpdate = toUpdate || svcChanged // apply route - rt, rtChanged, err := routesub.ApplyRoute(co.routeClient, routesub.DefaultRoute(console)) - - if err != nil { - allErrors = append(allErrors, err) + rt, rtChanged, rtErr := routesub.ApplyRoute(co.routeClient, routesub.DefaultRoute(consoleConfig)) + if rtErr != nil { + logrus.Infof("route error: %v", rtErr) + allErrors = append(allErrors, rtErr) } toUpdate = toUpdate || rtChanged // apply configmap (needs route) - _, cmChanged, err := resourceapply.ApplyConfigMap(co.configMapClient, configmapsub.DefaultConfigMap(console, rt)) - if err != nil { - allErrors = append(allErrors, err) + cm, cmChanged, cmErr := resourceapply.ApplyConfigMap(co.configMapClient, configmapsub.DefaultConfigMap(consoleConfig, rt)) + if cmErr != nil { + logrus.Infof("cm error: %v", cmErr) + allErrors = append(allErrors, cmErr) } toUpdate = toUpdate || cmChanged - // apply deployment is a bit more involved as it needs information about version & if we should - // force a rollout of the pods. at this point, configMap updates are the bool for this - defaultDeployment := deploymentsub.DefaultDeployment(console) - versionAvailability := &v1alpha12.VersionAvailability{ - Version: console.Spec.Version, - } - deploymentGeneration := resourcemerge.ExpectedDeploymentGeneration(defaultDeployment, versionAvailability) - redeployPods := cmChanged - _, dpChanged, err := resourceapply.ApplyDeployment(co.deploymentClient, defaultDeployment, deploymentGeneration, redeployPods) - if err != nil { - allErrors = append(allErrors, err) - } - toUpdate = toUpdate || dpChanged - - // shared sharedOAuthSecretBits := crypto.Random256BitsString() // apply oauth (needs route) defaultOauthClient := oauthsub.RegisterConsoleToOAuthClient(oauthsub.DefaultOauthClient(), rt, sharedOAuthSecretBits) - _, oauthChanged, err := oauthsub.ApplyOAuth(co.oauthClient, defaultOauthClient) - if err != nil { - allErrors = append(allErrors, err) + oa, oauthChanged, oauthErr := oauthsub.ApplyOAuth(co.oauthClient, defaultOauthClient) + if oauthErr != nil { + logrus.Infof("oauth error: %v", oauthErr) + allErrors = append(allErrors, oauthErr) } toUpdate = toUpdate || oauthChanged // apply secret - _, secretChanged, err := resourceapply.ApplySecret(co.secretsClient, secret.DefaultSecret(console,sharedOAuthSecretBits)) - if err != nil { - allErrors = append(allErrors, err) + sec, secretChanged, secErr := resourceapply.ApplySecret(co.secretsClient, secret.DefaultSecret(consoleConfig,sharedOAuthSecretBits)) + if secErr != nil { + logrus.Infof("sec error: %v", secErr) + allErrors = append(allErrors, secErr) } toUpdate = toUpdate || secretChanged + // apply deployment is a bit more involved as it needs information about version & if we should + // force a rollout of the pods. at this point, configMap updates are the bool for this + defaultDeployment := deploymentsub.DefaultDeployment(consoleConfig) + versionAvailability := &operatorv1alpha1.VersionAvailability{ + Version: consoleConfig.Spec.Version, + } + deploymentGeneration := resourcemerge.ExpectedDeploymentGeneration(defaultDeployment, versionAvailability) + // if anything changed, we can roll out the pods again to ensure latest + redeployPods := toUpdate + dep, dpChanged, depErr := resourceapply.ApplyDeployment(co.deploymentClient, defaultDeployment, deploymentGeneration, redeployPods) + if depErr != nil { + logrus.Infof("dep error: %v", depErr) + allErrors = append(allErrors, depErr) + } + toUpdate = toUpdate || dpChanged + + + // if any of our resources have svcChanged, we should update the CR. otherwise, skip this step. if toUpdate { + logrus.Infof("Sync_v400: To update Spec? %v", toUpdate) + setStatus(consoleConfig.Status, svc, rt, cm, dep, oa, sec) // update status on CR // pass in each of the above resources, possibly the // boolean for "changed" as well, and then assign a status @@ -107,6 +121,15 @@ func sync_v400(co *ConsoleOperator, console *v1alpha1.Console) error { return errutil.FilterOut(errutil.NewAggregate(allErrors), apierrors.IsNotFound) } +func setStatus(cs v1alpha1.ConsoleStatus, svc *corev1.Service, rt *routev1.Route, cm *corev1.ConfigMap, dep *appsv1.Deployment, oa *oauthv1.OAuthClient, sec *corev1.Secret) { + if rt.Spec.Host != "" { + // we have a host, yay + } else { + // no host, boo. + } + // what else. +} + //func DeleteAllResources(cr *v1alpha1.Console) error { // var errs []error diff --git a/pkg/console/subresource/util/util.go b/pkg/console/subresource/util/util.go index 913eead..f708cec 100644 --- a/pkg/console/subresource/util/util.go +++ b/pkg/console/subresource/util/util.go @@ -1,6 +1,7 @@ package util import ( + "fmt" "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" "github.com/openshift/console-operator/pkg/controller" "github.com/sirupsen/logrus" @@ -45,20 +46,21 @@ func SharedMeta() v1.ObjectMeta { func LogYaml(obj runtime.Object) { // REALLY NOISY, but handy for debugging: // deployJSON, err := json.Marshal(d) - deployYAML, err := yaml.Marshal(obj) + objYaml, err := yaml.Marshal(obj) if err != nil { - logrus.Info("failed to show deployment yaml in log") + logrus.Info("failed to show yaml in log") } - logrus.Infof("Deploying: %v", string(deployYAML)) + logrus.Infof("%v", string(objYaml)) } // objects can have more than one ownerRef, potentially func AddOwnerRef(obj v1.Object, ownerRef *v1.OwnerReference) { - if obj != nil { - if ownerRef != nil { - obj.SetOwnerReferences(append(obj.GetOwnerReferences(), *ownerRef)) - } - } + fmt.Println("AddOwnerRef() disabled.") + //if obj != nil { + // if ownerRef != nil { + // obj.SetOwnerReferences(append(obj.GetOwnerReferences(), *ownerRef)) + // } + //} } func OwnerRefFrom(cr *v1alpha1.Console) *v1.OwnerReference { From 4b3f802a072fbc150303c68bd97aaa3cb5a93359 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Tue, 20 Nov 2018 10:57:00 -0500 Subject: [PATCH 21/24] Return to functioning reconcile loop - Temporarily drop ApplyRoute() to more carefully GetOrCreate route - ensures we don't stomp on the Spec.host - Update Secret to manually create encoded secret - ApplySecret() from library-go ignores Spec.StringData - PR this to library-go in future - Stub in func for CR.Status via Sync loop - will be a follow-up PR - Stub in some specific status fields on Cr.Status - will be a follow-up PR --- pkg/apis/console/v1alpha1/types.go | 3 + pkg/console/operator/operator.go | 2 +- pkg/console/operator/sync_v400.go | 184 ++++++++++++------ .../subresource/oauthclient/oauthclient.go | 8 +- pkg/console/subresource/route/route.go | 50 ++++- pkg/console/subresource/secret/secret.go | 31 ++- 6 files changed, 210 insertions(+), 68 deletions(-) diff --git a/pkg/apis/console/v1alpha1/types.go b/pkg/apis/console/v1alpha1/types.go index 72149b6..bf81461 100644 --- a/pkg/apis/console/v1alpha1/types.go +++ b/pkg/apis/console/v1alpha1/types.go @@ -32,6 +32,9 @@ type ConsoleSpec struct { type ConsoleStatus struct { v1alpha1.OperatorStatus + // set once the router has a default host name + DefaultHostName string `json:"defaultHostName"` + OAuthSecret string `json""oauthSecret"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/console/operator/operator.go b/pkg/console/operator/operator.go index dc8d1f7..688fccf 100644 --- a/pkg/console/operator/operator.go +++ b/pkg/console/operator/operator.go @@ -197,7 +197,7 @@ func (c *ConsoleOperator) sync(_ interface{}) error { // v4.0.0 or nil case v311_to_401.BetweenOrEmpty(currentActualVersion): logrus.Println("Sync-4.0.0") - sync_v400(c, operatorConfig) + outConfig, err = sync_v400(c, outConfig) // errs = append(errs, err) // if err == nil { outConfig.Status.TaskSummary = "sync-4.0.0" diff --git a/pkg/console/operator/sync_v400.go b/pkg/console/operator/sync_v400.go index 4318fe6..f617395 100644 --- a/pkg/console/operator/sync_v400.go +++ b/pkg/console/operator/sync_v400.go @@ -1,87 +1,117 @@ package operator import ( + // 3rd party "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + coreclientv1 "k8s.io/client-go/kubernetes/typed/core/v1" // kube appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" errutil "k8s.io/apimachinery/pkg/util/errors" - // openshift oauthv1 "github.com/openshift/api/oauth/v1" operatorv1alpha1 "github.com/openshift/api/operator/v1alpha1" routev1 "github.com/openshift/api/route/v1" - "github.com/openshift/console-operator/pkg/console/subresource/secret" + oauthclientv1 "github.com/openshift/client-go/oauth/clientset/versioned/typed/oauth/v1" + // openshift + "github.com/openshift/console-operator/pkg/controller" "github.com/openshift/console-operator/pkg/crypto" - "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" "github.com/openshift/library-go/pkg/operator/resource/resourceapply" + "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" // operator "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" - servicesub "github.com/openshift/console-operator/pkg/console/subresource/service" configmapsub "github.com/openshift/console-operator/pkg/console/subresource/configmap" deploymentsub "github.com/openshift/console-operator/pkg/console/subresource/deployment" oauthsub "github.com/openshift/console-operator/pkg/console/subresource/oauthclient" routesub "github.com/openshift/console-operator/pkg/console/subresource/route" - + secretsub "github.com/openshift/console-operator/pkg/console/subresource/secret" + servicesub "github.com/openshift/console-operator/pkg/console/subresource/service" ) // runs the standard v4.0.0 reconcile loop -func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) error { +// the Apply logic is a bit tricky. +// - Default Route is incomplete, we expect the server to fill out host, +// so should not stomp on it after the initial run +// - other resources can be a tad tricky as well. +func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1.Console, error) { // aggregate the errors from this: allErrors := []error{} toUpdate := false + // apply service - svc, svcChanged, svcErr := resourceapply.ApplyService(co.serviceClient, servicesub.DefaultService(consoleConfig)) + _, svcChanged, svcErr := resourceapply.ApplyService(co.serviceClient, servicesub.DefaultService(consoleConfig)) if svcErr != nil { - logrus.Infof("service error: %v", svcErr) + logrus.Errorf("service error: %v", svcErr) allErrors = append(allErrors, svcErr) } toUpdate = toUpdate || svcChanged + // apply route - rt, rtChanged, rtErr := routesub.ApplyRoute(co.routeClient, routesub.DefaultRoute(consoleConfig)) + // TODO: + // - DefaultRoute() should literally just be *Default* + // - get the Default(). + // - if exists, great. if not, Create() + // - this would avoid the stomping if we use Apply() as it won't merge back... + // - EnsureRouteSpec() + // - check that everything we need is there + // - ApplyRoute() + // - the job of ApplyRoute() is to ensure exists, then update correctly via + // merge. This *correctly* is generic, not specific to what OUR route needs. + // - therefore, it is appropriate to split apart EnsureRouteSpec() from ApplyRoute() + // - note that EnsureRouteSpec() may not be great long term, depends... + rt, rtIsNew, rtErr := routesub.GetOrCreate(co.routeClient, routesub.DefaultRoute(consoleConfig)) + // rt, rtChanged, rtErr := routesub.ApplyRoute(co.routeClient, routesub.DefaultRoute(consoleConfig)) if rtErr != nil { - logrus.Infof("route error: %v", rtErr) + logrus.Errorf("route error: %v", rtErr) allErrors = append(allErrors, rtErr) } - toUpdate = toUpdate || rtChanged + toUpdate = toUpdate || rtIsNew + // apply configmap (needs route) - cm, cmChanged, cmErr := resourceapply.ApplyConfigMap(co.configMapClient, configmapsub.DefaultConfigMap(consoleConfig, rt)) + _, cmChanged, cmErr := resourceapply.ApplyConfigMap(co.configMapClient, configmapsub.DefaultConfigMap(consoleConfig, rt)) if cmErr != nil { - logrus.Infof("cm error: %v", cmErr) + logrus.Errorf("cm error: %v", cmErr) allErrors = append(allErrors, cmErr) } toUpdate = toUpdate || cmChanged + // the deployment will need to know if the secret changed so this must be func scoped + secretChanged := false + oauthChanged := false + if !secretsMatch(co.secretsClient, co.oauthClient) { + // shared secret bits + // sharedOAuthSecretBits := crypto.RandomBits(256) + sharedOAuthSecretBits := crypto.Random256BitsString() + + // apply oauth (needs route) + defaultOauthClient := oauthsub.RegisterConsoleToOAuthClient(oauthsub.DefaultOauthClient(), rt, sharedOAuthSecretBits) + _, oauthChanged, oauthErr := oauthsub.ApplyOAuth(co.oauthClient, defaultOauthClient) + if oauthErr != nil { + logrus.Errorf("oauth error: %v", oauthErr) + allErrors = append(allErrors, oauthErr) + } + toUpdate = toUpdate || oauthChanged + + // apply secret + _, secretChanged, secErr := resourceapply.ApplySecret(co.secretsClient, secretsub.DefaultSecret(consoleConfig, sharedOAuthSecretBits)) + if secErr != nil { + logrus.Errorf("sec error: %v", secErr) + allErrors = append(allErrors, secErr) + } + toUpdate = toUpdate || secretChanged - // shared - sharedOAuthSecretBits := crypto.Random256BitsString() - - - // apply oauth (needs route) - defaultOauthClient := oauthsub.RegisterConsoleToOAuthClient(oauthsub.DefaultOauthClient(), rt, sharedOAuthSecretBits) - oa, oauthChanged, oauthErr := oauthsub.ApplyOAuth(co.oauthClient, defaultOauthClient) - if oauthErr != nil { - logrus.Infof("oauth error: %v", oauthErr) - allErrors = append(allErrors, oauthErr) } - toUpdate = toUpdate || oauthChanged - - - // apply secret - sec, secretChanged, secErr := resourceapply.ApplySecret(co.secretsClient, secret.DefaultSecret(consoleConfig,sharedOAuthSecretBits)) - if secErr != nil { - logrus.Infof("sec error: %v", secErr) - allErrors = append(allErrors, secErr) - } - toUpdate = toUpdate || secretChanged - + // TODO: deployment changes too much, dont trigger loop. + // the Apply() again is prob incorrect in that our DefaultDeploymnet() is + // too much... and there is prob something that gets stomped. // apply deployment is a bit more involved as it needs information about version & if we should // force a rollout of the pods. at this point, configMap updates are the bool for this defaultDeployment := deploymentsub.DefaultDeployment(consoleConfig) @@ -89,45 +119,89 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) error { Version: consoleConfig.Spec.Version, } deploymentGeneration := resourcemerge.ExpectedDeploymentGeneration(defaultDeployment, versionAvailability) - // if anything changed, we can roll out the pods again to ensure latest - redeployPods := toUpdate - dep, dpChanged, depErr := resourceapply.ApplyDeployment(co.deploymentClient, defaultDeployment, deploymentGeneration, redeployPods) + // if configMap or secrets change, we need to deploy a new pod + redeployPods := cmChanged || secretChanged + _, depChanged, depErr := resourceapply.ApplyDeployment(co.deploymentClient, defaultDeployment, deploymentGeneration, redeployPods) if depErr != nil { logrus.Infof("dep error: %v", depErr) allErrors = append(allErrors, depErr) } - toUpdate = toUpdate || dpChanged + toUpdate = toUpdate || depChanged + logrus.Printf("service changed: %v \n", svcChanged) + logrus.Printf("route is new: %v \n", rtIsNew) + logrus.Printf("configMap changed: %v \n", cmChanged) + logrus.Printf("secret changed: %v \n", secretChanged) + logrus.Printf("oauth changed: %v \n", oauthChanged) + logrus.Printf("deployment changed: %v \n", depChanged) + logrus.Println("------------") + // if any of our resources have svcChanged, we should update the CR. otherwise, skip this step. if toUpdate { logrus.Infof("Sync_v400: To update Spec? %v", toUpdate) - setStatus(consoleConfig.Status, svc, rt, cm, dep, oa, sec) - // update status on CR - // pass in each of the above resources, possibly the - // boolean for "changed" as well, and then assign a status - // on the CR.Status. Be sure to account for a nil return value - // as some of our resources (oauthlient, configmap) may simply - // not be possible to create if they lack the appropriate inputs. - // in this case, the Status should CLEARLY indicate this to the user. - // Once the resource is correctly created, the status should be updated - // again. This should be pretty simple and straightforward work. - // update cluster operator status... i believe this - // should be automatic so long as the CR.Status is - // properly filled out with the appropriate values. + // TODO: set the status. + // setStatus(consoleConfig.Status, svc, rt, cm, dep, oa, sec) + } + + return consoleConfig, errutil.FilterOut(errutil.NewAggregate(allErrors), apierrors.IsNotFound) +} + + +func secretsMatch(secretGetter coreclientv1.SecretsGetter, clientsGetter oauthclientv1.OAuthClientsGetter) bool { + secret, err := secretGetter.Secrets(controller.TargetNamespace).Get(deploymentsub.ConsoleOauthConfigName, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + return false + } + oauthClient, err := clientsGetter.OAuthClients().Get(controller.OpenShiftConsoleName, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + return false } - return errutil.FilterOut(errutil.NewAggregate(allErrors), apierrors.IsNotFound) + return secretAndOauthMatch(secret, oauthClient) } +func secretAndOauthMatch(secret *corev1.Secret, client *oauthv1.OAuthClient) bool { + secretString := secretsub.GetSecretString(secret) + clientSecretString := oauthsub.GetSecretString(client) + return secretString == clientSecretString +} + + +// update status on CR +// pass in each of the above resources, possibly the +// boolean for "changed" as well, and then assign a status +// on the CR.Status. Be sure to account for a nil return value +// as some of our resources (oauthlient, configmap) may simply +// not be possible to create if they lack the appropriate inputs. +// in this case, the Status should CLEARLY indicate this to the user. +// Once the resource is correctly created, the status should be updated +// again. This should be pretty simple and straightforward work. +// update cluster operator status... i believe this +// should be automatic so long as the CR.Status is +// properly filled out with the appropriate values. func setStatus(cs v1alpha1.ConsoleStatus, svc *corev1.Service, rt *routev1.Route, cm *corev1.ConfigMap, dep *appsv1.Deployment, oa *oauthv1.OAuthClient, sec *corev1.Secret) { + logrus.Println("setStatus()") + logrus.Println("-----------") + + // TODO: handle custom hosts as well if rt.Spec.Host != "" { - // we have a host, yay + cs.DefaultHostName = rt.Spec.Host + logrus.Printf("stats.DefaultHostName set to %v", rt.Spec.Host) } else { - // no host, boo. + cs.DefaultHostName = "" + logrus.Printf("stats.DefaultHostName set to %v", "") } - // what else. + + if secretAndOauthMatch(sec, oa) { + cs.OAuthSecret = "valid" + logrus.Printf("status.OAuthSecret is valid") + } else { + cs.OAuthSecret = "mismatch" + logrus.Printf("status.OAuthSecret is mismatch") + } + } diff --git a/pkg/console/subresource/oauthclient/oauthclient.go b/pkg/console/subresource/oauthclient/oauthclient.go index efb7ee7..c6fd959 100644 --- a/pkg/console/subresource/oauthclient/oauthclient.go +++ b/pkg/console/subresource/oauthclient/oauthclient.go @@ -55,7 +55,8 @@ func RegisterConsoleToOAuthClient(client *oauthv1.OAuthClient, route *v1.Route, // the console client.RedirectURIs = []string{} client.RedirectURIs = append(client.RedirectURIs, https(route.Spec.Host)) - client.Secret = randomBits + // client.Secret = randomBits + client.Secret = string(randomBits) return client } @@ -85,6 +86,7 @@ func DefaultOauthClient() *oauthv1.OAuthClient{ } } +// TODO: technically, this should take targetPort from route.spec.port.targetPort func https(host string) string { protocol := "https://" if host == "" { @@ -98,3 +100,7 @@ func https(host string) string { logrus.Infof("host updated from %s to %s", host, secured) return secured } + +func GetSecretString(client *oauthv1.OAuthClient) string { + return client.Secret +} diff --git a/pkg/console/subresource/route/route.go b/pkg/console/subresource/route/route.go index 8fcf08a..6e0dde3 100644 --- a/pkg/console/subresource/route/route.go +++ b/pkg/console/subresource/route/route.go @@ -1,17 +1,36 @@ package route import ( + // kube + "k8s.io/apimachinery/pkg/api/equality" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + // openshift + "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" routev1 "github.com/openshift/api/route/v1" routeclient "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1" + // operator "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" "github.com/openshift/console-operator/pkg/console/subresource/util" "github.com/openshift/console-operator/pkg/controller" - "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" ) +// this is a stop gap for now. we want ApplyRoute correct, but don't need it yet +func GetOrCreate(client routeclient.RoutesGetter, required *routev1.Route) (*routev1.Route, bool, error) { + isNew := false + existing, err := client.Routes(required.Namespace).Get(required.Name, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + isNew = true + actual, err := client.Routes(required.Namespace).Create(required) + return actual, isNew, err + } + if err != nil { + return nil, isNew, err + } + return existing, isNew, nil +} + // TODO: ApplyRoute // - should look like resourceapply.ApplyService // - should be PR'd to client-go @@ -25,11 +44,32 @@ func ApplyRoute(client routeclient.RoutesGetter, required *routev1.Route) (*rout if err != nil { return nil, false, err } - // otherwise update + modified := resourcemerge.BoolPtr(false) resourcemerge.EnsureObjectMeta(modified, &existing.ObjectMeta, required.ObjectMeta) + // possibly this should just be a DeepEqual on Spec... + hostSame := equality.Semantic.DeepEqual(existing.Spec.Host, required.Spec.Host) + portSame := equality.Semantic.DeepEqual(existing.Spec.Port, required.Spec.Port) + tlsSame := equality.Semantic.DeepEqual(existing.Spec.TLS, required.Spec.TLS) + targetSame := equality.Semantic.DeepEqual(existing.Spec.To, required.Spec.To) + wildcardSame := equality.Semantic.DeepEqual(existing.Spec.WildcardPolicy, required.Spec.WildcardPolicy) + // if nothing we care about changed, do nothing. this would be good to + // PR to library-go and ensure we get it right + if hostSame && portSame && tlsSame && targetSame && wildcardSame { + return existing, false, nil + } + + // TODO: + // - we dont want to squash host, which is assigned by the server + // - figure out how to handle this properly, some props are assigned later toWrite := existing + // - CAN we just squash the .Spec here? or is that incorrect? Apply should + // be careful, but simple, know nothing about the business logic of the + // operator itself. Therefore, if one does ApplyRoute(someRoute) would they + // expect it simply to set this, regardless of what is on the server already? + // at this point probably should assume the caller already did a .Get(route) + // and merged properties, if that path was desired. toWrite.Spec = *required.Spec.DeepCopy() actual, err := client.Routes(required.Namespace).Update(toWrite) diff --git a/pkg/console/subresource/secret/secret.go b/pkg/console/subresource/secret/secret.go index 1495217..d8374cb 100644 --- a/pkg/console/subresource/secret/secret.go +++ b/pkg/console/subresource/secret/secret.go @@ -1,23 +1,42 @@ package secret import ( - "k8s.io/api/core/v1" + // 3rd + "github.com/sirupsen/logrus" + // kube + corev1 "k8s.io/api/core/v1" + // openshift "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" "github.com/openshift/console-operator/pkg/console/subresource/deployment" "github.com/openshift/console-operator/pkg/console/subresource/util" ) -const dataKey = "clientsecret" +const ClientSecretKey = "clientSecret" -func DefaultSecret(cr *v1alpha1.Console, randomBits string) *v1.Secret { +func DefaultSecret(cr *v1alpha1.Console, randomBits string) *corev1.Secret { + logrus.Printf("DefaultSecret() %v", randomBits) meta := util.SharedMeta() meta.Name = deployment.ConsoleOauthConfigName - secret := &v1.Secret{ + + secret := &corev1.Secret{ ObjectMeta: meta, } - secret.StringData = map[string]string{ - dataKey: randomBits, + + // TODO: open bug in client-go, it drops StringData :/ + //secret.StringData = map[string]string{ + // ClientSecretKey: randomBits, + //} + + secret.Data = map[string][]byte{ + ClientSecretKey: []byte(randomBits), } + + util.AddOwnerRef(secret, util.OwnerRefFrom(cr)) return secret } + +func GetSecretString(secret *corev1.Secret) string { + return string(secret.Data[ClientSecretKey]) +} + From d4a81c91477a8454eb0c1a73c5ce713bb9354144 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Tue, 20 Nov 2018 16:44:27 -0500 Subject: [PATCH 22/24] Handle ManagementState: Removed, refactor 'Default' resource functions to extract 'Stub' --- pkg/console/operator/operator.go | 37 ++++++++++++++- pkg/console/operator/sync_v400.go | 47 +++++-------------- .../subresource/configmap/configmap.go | 15 ++++-- .../subresource/deployment/deployment.go | 9 ++++ .../subresource/oauthclient/oauthclient.go | 7 +-- pkg/console/subresource/route/route.go | 38 ++++++++------- pkg/console/subresource/secret/secret.go | 19 ++++---- pkg/console/subresource/service/service.go | 37 ++++++++++----- 8 files changed, 129 insertions(+), 80 deletions(-) diff --git a/pkg/console/operator/operator.go b/pkg/console/operator/operator.go index 688fccf..cb5051e 100644 --- a/pkg/console/operator/operator.go +++ b/pkg/console/operator/operator.go @@ -3,6 +3,13 @@ package operator import ( // standard lib "fmt" + "github.com/openshift/console-operator/pkg/console/subresource/configmap" + "github.com/openshift/console-operator/pkg/console/subresource/deployment" + "github.com/openshift/console-operator/pkg/console/subresource/oauthclient" + "github.com/openshift/console-operator/pkg/console/subresource/route" + "github.com/openshift/console-operator/pkg/console/subresource/secret" + "github.com/openshift/console-operator/pkg/console/subresource/service" + // 3rd party "github.com/blang/semver" "github.com/sirupsen/logrus" @@ -158,12 +165,15 @@ func (c *ConsoleOperator) sync(_ interface{}) error { switch operatorConfig.Spec.ManagementState { case operatorsv1alpha1.Managed: + fmt.Println("Console is in a managed state.") // handled below case operatorsv1alpha1.Unmanaged: + fmt.Println("Console is in an unmanaged state.") return nil // take a look @ https://github.com/openshift/service-serving-cert-signer/blob/master/pkg/operator/operator.go#L86 case operatorsv1alpha1.Removed: - return utilerrors.FilterOut(c.secretsClient.Secrets(controller.TargetNamespace).Delete(controller.ResourceName, nil), errors.IsNotFound) + fmt.Println("Console has been removed.") + return c.deleteAllResources(operatorConfig) default: // TODO should update status return fmt.Errorf("unknown state: %v", operatorConfig.Spec.ManagementState) @@ -216,7 +226,32 @@ func (c *ConsoleOperator) sync(_ interface{}) error { return utilerrors.NewAggregate(errs) } +// this may need to move to sync_v400 if versions ever have custom delete logic +func (c *ConsoleOperator) deleteAllResources(cr *consolev1alpha1.Console) error { + var errs []error + + // service + errs = append(errs, c.serviceClient.Services(controller.TargetNamespace).Delete(service.Stub().Name, &metav1.DeleteOptions{})) + // route + errs = append(errs, c.routeClient.Routes(controller.TargetNamespace).Delete(route.Stub().Name, &metav1.DeleteOptions{})) + // configmap + errs = append(errs, c.configMapClient.ConfigMaps(controller.TargetNamespace).Delete(configmap.Stub().Name, &metav1.DeleteOptions{})) + // secret + errs = append(errs, c.secretsClient.Secrets(controller.TargetNamespace).Delete(secret.Stub().Name, &metav1.DeleteOptions{})) + // existingOAuthClient is not a delete, it is a deregister/neutralize + existingOAuthClient, getAuthErr := c.oauthClient.OAuthClients().Get(oauthclient.Stub().Name, metav1.GetOptions{}) + errs = append(errs, getAuthErr) + _, updateAuthErr := c.oauthClient.OAuthClients().Update(oauthclient.DeRegisterConsoleFromOAuthClient(existingOAuthClient)) + errs = append(errs, updateAuthErr) + // deployment + errs = append(errs, c.deploymentClient.Deployments(controller.TargetNamespace).Delete(deployment.Stub().Name, &metav1.DeleteOptions{})) + + return utilerrors.FilterOut(utilerrors.NewAggregate(errs), errors.IsNotFound) +} + +// this may need to eventually live under each sync version, depending on if there is +// custom sync logic func (c *ConsoleOperator) defaultConsole() *consolev1alpha1.Console { return &consolev1alpha1.Console{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/console/operator/sync_v400.go b/pkg/console/operator/sync_v400.go index f617395..3e6956d 100644 --- a/pkg/console/operator/sync_v400.go +++ b/pkg/console/operator/sync_v400.go @@ -44,7 +44,7 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1. // apply service _, svcChanged, svcErr := resourceapply.ApplyService(co.serviceClient, servicesub.DefaultService(consoleConfig)) if svcErr != nil { - logrus.Errorf("service error: %v", svcErr) + logrus.Errorf("%q: %v \n", "service", svcErr) allErrors = append(allErrors, svcErr) } toUpdate = toUpdate || svcChanged @@ -53,21 +53,14 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1. // apply route // TODO: - // - DefaultRoute() should literally just be *Default* - // - get the Default(). - // - if exists, great. if not, Create() - // - this would avoid the stomping if we use Apply() as it won't merge back... - // - EnsureRouteSpec() - // - check that everything we need is there - // - ApplyRoute() - // - the job of ApplyRoute() is to ensure exists, then update correctly via - // merge. This *correctly* is generic, not specific to what OUR route needs. - // - therefore, it is appropriate to split apart EnsureRouteSpec() from ApplyRoute() - // - note that EnsureRouteSpec() may not be great long term, depends... + // - once we handle a custom hostname, upgrade to ApplyRoute() + // - be sure to test that we don't trigger an infinite loop by stomping on the + // default host name set by the server, or any other values. The ApplyRoute() + // logic will have to be sound. rt, rtIsNew, rtErr := routesub.GetOrCreate(co.routeClient, routesub.DefaultRoute(consoleConfig)) // rt, rtChanged, rtErr := routesub.ApplyRoute(co.routeClient, routesub.DefaultRoute(consoleConfig)) if rtErr != nil { - logrus.Errorf("route error: %v", rtErr) + logrus.Errorf("%q: %v \n", "route", rtErr) allErrors = append(allErrors, rtErr) } toUpdate = toUpdate || rtIsNew @@ -77,12 +70,14 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1. // apply configmap (needs route) _, cmChanged, cmErr := resourceapply.ApplyConfigMap(co.configMapClient, configmapsub.DefaultConfigMap(consoleConfig, rt)) if cmErr != nil { - logrus.Errorf("cm error: %v", cmErr) + logrus.Errorf("%q: %v \n", "configmap", cmErr) allErrors = append(allErrors, cmErr) } toUpdate = toUpdate || cmChanged - // the deployment will need to know if the secret changed so this must be func scoped + // TODO: clean up the scoping here + // - the deployment needs to know about the change value in order to address updates, + // but the wrapper is needed to avoid triggering loops unnecessarily secretChanged := false oauthChanged := false if !secretsMatch(co.secretsClient, co.oauthClient) { @@ -94,7 +89,7 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1. defaultOauthClient := oauthsub.RegisterConsoleToOAuthClient(oauthsub.DefaultOauthClient(), rt, sharedOAuthSecretBits) _, oauthChanged, oauthErr := oauthsub.ApplyOAuth(co.oauthClient, defaultOauthClient) if oauthErr != nil { - logrus.Errorf("oauth error: %v", oauthErr) + logrus.Errorf("%q: %v \n", "oauthclient", oauthErr) allErrors = append(allErrors, oauthErr) } toUpdate = toUpdate || oauthChanged @@ -103,6 +98,7 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1. _, secretChanged, secErr := resourceapply.ApplySecret(co.secretsClient, secretsub.DefaultSecret(consoleConfig, sharedOAuthSecretBits)) if secErr != nil { logrus.Errorf("sec error: %v", secErr) + logrus.Errorf("%q: %v \n", "secret", secErr) allErrors = append(allErrors, secErr) } toUpdate = toUpdate || secretChanged @@ -123,7 +119,7 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1. redeployPods := cmChanged || secretChanged _, depChanged, depErr := resourceapply.ApplyDeployment(co.deploymentClient, defaultDeployment, deploymentGeneration, redeployPods) if depErr != nil { - logrus.Infof("dep error: %v", depErr) + logrus.Errorf("%q: %v \n", "deployment", depErr) allErrors = append(allErrors, depErr) } toUpdate = toUpdate || depChanged @@ -203,20 +199,3 @@ func setStatus(cs v1alpha1.ConsoleStatus, svc *corev1.Service, rt *routev1.Route } } - - -//func DeleteAllResources(cr *v1alpha1.Console) error { -// var errs []error -// for _, fn := range []func(*v1alpha1.Console) error{ -// DeleteService, -// DeleteRoute, -// DeleteConfigMap, -// DeleteDeployment, -// DeleteOAuthSecret, -// // we don't own it and can't create or delete it. however, we can update it -// NeutralizeOAuthClient, -// } { -// errs = append(errs, fn(cr)) -// } -// return errutil.FilterOut(errutil.NewAggregate(errs), errors.IsNotFound) -//} diff --git a/pkg/console/subresource/configmap/configmap.go b/pkg/console/subresource/configmap/configmap.go index ab1afb5..d26301d 100644 --- a/pkg/console/subresource/configmap/configmap.go +++ b/pkg/console/subresource/configmap/configmap.go @@ -37,16 +37,21 @@ func DefaultConfigMap(cr *v1alpha1.Console, rt *v1.Route) *corev1.ConfigMap { return nil } host := rt.Spec.Host + config := NewYamlConfigString(host) + configMap := Stub() + configMap.Data = map[string]string{ + consoleConfigYamlFile: config, + } + util.AddOwnerRef(configMap, util.OwnerRefFrom(cr)) + return configMap +} + +func Stub() *corev1.ConfigMap { meta := util.SharedMeta() meta.Name = ConsoleConfigMapName - config := NewYamlConfigString(host) configMap := &corev1.ConfigMap{ ObjectMeta: meta, - Data: map[string]string{ - consoleConfigYamlFile: config, - }, } - util.AddOwnerRef(configMap, util.OwnerRefFrom(cr)) return configMap } diff --git a/pkg/console/subresource/deployment/deployment.go b/pkg/console/subresource/deployment/deployment.go index 439f362..e19ffa1 100644 --- a/pkg/console/subresource/deployment/deployment.go +++ b/pkg/console/subresource/deployment/deployment.go @@ -92,6 +92,15 @@ func DefaultDeployment(cr *v1alpha1.Console) *appsv1.Deployment { return deployment } +func Stub() *appsv1.Deployment { + meta := util.SharedMeta() + dep := &appsv1.Deployment{ + ObjectMeta: meta, + } + return dep +} + + // deduplication, use the same volume config to generate Volumes, and VolumeMounts func consoleVolumes(vc []volumeConfig) []corev1.Volume { vols := make([]corev1.Volume, len(vc)) diff --git a/pkg/console/subresource/oauthclient/oauthclient.go b/pkg/console/subresource/oauthclient/oauthclient.go index c6fd959..dbbc7e3 100644 --- a/pkg/console/subresource/oauthclient/oauthclient.go +++ b/pkg/console/subresource/oauthclient/oauthclient.go @@ -76,13 +76,14 @@ func DeRegisterConsoleFromOAuthClient(client *oauthv1.OAuthClient) *oauthv1.OAut func DefaultOauthClient() *oauthv1.OAuthClient{ // we cannot set an ownerRef on the OAuthClient as it is // a cluster scoped resource. + return Stub() +} + +func Stub() *oauthv1.OAuthClient{ return &oauthv1.OAuthClient{ ObjectMeta: metav1.ObjectMeta{ Name: controller.OpenShiftConsoleName, }, - // we can't really set these here yet but need them - // RedirectURIs: []string{}, - // Secret: crypto.Random256BitsString(), } } diff --git a/pkg/console/subresource/route/route.go b/pkg/console/subresource/route/route.go index 6e0dde3..fc440dd 100644 --- a/pkg/console/subresource/route/route.go +++ b/pkg/console/subresource/route/route.go @@ -80,24 +80,30 @@ func DefaultRoute(cr *v1alpha1.Console) *routev1.Route { meta := util.SharedMeta() meta.Name = controller.OpenShiftConsoleShortName weight := int32(100) - route := &routev1.Route{ - ObjectMeta: meta, - Spec: routev1.RouteSpec{ - To: routev1.RouteTargetReference{ - Kind: "Service", - Name: meta.Name, - Weight: &weight, - }, - Port: &routev1.RoutePort{ - TargetPort: intstr.FromString("https"), - }, - TLS: &routev1.TLSConfig{ - Termination: routev1.TLSTerminationReencrypt, - InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect, - }, - WildcardPolicy: routev1.WildcardPolicyNone, + route := Stub() + route.Spec = routev1.RouteSpec{ + To: routev1.RouteTargetReference{ + Kind: "Service", + Name: meta.Name, + Weight: &weight, + }, + Port: &routev1.RoutePort{ + TargetPort: intstr.FromString("https"), + }, + TLS: &routev1.TLSConfig{ + Termination: routev1.TLSTerminationReencrypt, + InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect, }, + WildcardPolicy: routev1.WildcardPolicyNone, } util.AddOwnerRef(route, util.OwnerRefFrom(cr)) return route } + +func Stub() *routev1.Route { + meta := util.SharedMeta() + meta.Name = controller.OpenShiftConsoleShortName + return &routev1.Route{ + ObjectMeta: meta, + } +} diff --git a/pkg/console/subresource/secret/secret.go b/pkg/console/subresource/secret/secret.go index d8374cb..2bcd43c 100644 --- a/pkg/console/subresource/secret/secret.go +++ b/pkg/console/subresource/secret/secret.go @@ -15,27 +15,30 @@ const ClientSecretKey = "clientSecret" func DefaultSecret(cr *v1alpha1.Console, randomBits string) *corev1.Secret { logrus.Printf("DefaultSecret() %v", randomBits) - meta := util.SharedMeta() - meta.Name = deployment.ConsoleOauthConfigName - - secret := &corev1.Secret{ - ObjectMeta: meta, - } + secret := Stub() // TODO: open bug in client-go, it drops StringData :/ //secret.StringData = map[string]string{ // ClientSecretKey: randomBits, //} - secret.Data = map[string][]byte{ ClientSecretKey: []byte(randomBits), } - util.AddOwnerRef(secret, util.OwnerRefFrom(cr)) return secret } +func Stub() *corev1.Secret { + meta := util.SharedMeta() + meta.Name = deployment.ConsoleOauthConfigName + + secret := &corev1.Secret{ + ObjectMeta: meta, + } + return secret +} + func GetSecretString(secret *corev1.Secret) string { return string(secret.Data[ClientSecretKey]) } diff --git a/pkg/console/subresource/service/service.go b/pkg/console/subresource/service/service.go index 9654f18..e1a5b67 100644 --- a/pkg/console/subresource/service/service.go +++ b/pkg/console/subresource/service/service.go @@ -28,23 +28,34 @@ func DefaultService(cr *v1alpha1.Console) *v1.Service { meta.Annotations = map[string]string{ ServingCertSecretAnnotation: ConsoleServingCertName, } - service := &v1.Service{ - ObjectMeta: meta, - Spec: v1.ServiceSpec{ - Ports: []v1.ServicePort{ - { - Name: consolePortName, - Protocol: v1.ProtocolTCP, - Port: consolePort, - TargetPort: intstr.FromInt(consoleTargetPort), - }, + service := Stub() + service.Spec = v1.ServiceSpec{ + Ports: []v1.ServicePort{ + { + Name: consolePortName, + Protocol: v1.ProtocolTCP, + Port: consolePort, + TargetPort: intstr.FromInt(consoleTargetPort), }, - Selector: labels, - Type: "ClusterIP", - SessionAffinity: "None", }, + Selector: labels, + Type: "ClusterIP", + SessionAffinity: "None", } util.AddOwnerRef(service, util.OwnerRefFrom(cr)) return service } + +func Stub() *v1.Service { + meta := util.SharedMeta() + meta.Name = controller.OpenShiftConsoleShortName + meta.Annotations = map[string]string{ + ServingCertSecretAnnotation: ConsoleServingCertName, + } + service := &v1.Service{ + ObjectMeta: meta, + } + return service +} + From e1d605203dfffad6bf4f9fff989e6e27a69eea29 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Tue, 20 Nov 2018 17:09:31 -0500 Subject: [PATCH 23/24] Clean up excessive comments --- examples/cr.yaml | 1 + pkg/console/operator/operator.go | 17 +++++--- pkg/console/operator/sync_v400.go | 43 +++++++------------ .../subresource/configmap/configmap.go | 27 +++--------- .../subresource/deployment/deployment.go | 6 +-- .../subresource/oauthclient/oauthclient.go | 41 ++++-------------- pkg/console/subresource/route/route.go | 10 +++-- pkg/console/subresource/secret/secret.go | 2 +- pkg/console/subresource/service/service.go | 3 +- pkg/console/subresource/util/util.go | 19 ++++++++ pkg/console/version/version.go | 4 +- 11 files changed, 71 insertions(+), 102 deletions(-) diff --git a/examples/cr.yaml b/examples/cr.yaml index 2957d22..265da4b 100644 --- a/examples/cr.yaml +++ b/examples/cr.yaml @@ -5,6 +5,7 @@ apiVersion: "console.openshift.io/v1alpha1" kind: "Console" metadata: # Do not change the name, the operator explicitly requires this name to match as the console is a singleton. + # must match name defined in pkg/controller/api.go name: console-operator-resource namespace: openshift-console spec: diff --git a/pkg/console/operator/operator.go b/pkg/console/operator/operator.go index cb5051e..908ecde 100644 --- a/pkg/console/operator/operator.go +++ b/pkg/console/operator/operator.go @@ -190,7 +190,7 @@ func (c *ConsoleOperator) sync(_ interface{}) error { currentActualVersion = &ver } } - // not actually using ATM + // not yet using, we target only 4.0.0 desiredVersion, err := semver.Parse(operatorConfig.Spec.Version) if err != nil { // TODO report failing status, we may actually attempt to do this in the "normal" error handling @@ -208,11 +208,12 @@ func (c *ConsoleOperator) sync(_ interface{}) error { case v311_to_401.BetweenOrEmpty(currentActualVersion): logrus.Println("Sync-4.0.0") outConfig, err = sync_v400(c, outConfig) - // errs = append(errs, err) - // if err == nil { - outConfig.Status.TaskSummary = "sync-4.0.0" - outConfig.Status.CurrentAvailability = &operatorsv1alpha1.VersionAvailability{ - Version: desiredVersion.String(), + errs = append(errs, err) + if err == nil { + outConfig.Status.TaskSummary = "sync-4.0.0" + outConfig.Status.CurrentAvailability = &operatorsv1alpha1.VersionAvailability{ + Version: desiredVersion.String(), + } } default: logrus.Printf("Unrecognized version. Desired %s, Actual %s", desiredVersion, currentActualVersion) @@ -229,7 +230,6 @@ func (c *ConsoleOperator) sync(_ interface{}) error { // this may need to move to sync_v400 if versions ever have custom delete logic func (c *ConsoleOperator) deleteAllResources(cr *consolev1alpha1.Console) error { var errs []error - // service errs = append(errs, c.serviceClient.Services(controller.TargetNamespace).Delete(service.Stub().Name, &metav1.DeleteOptions{})) // route @@ -260,9 +260,12 @@ func (c *ConsoleOperator) defaultConsole() *consolev1alpha1.Console { }, Spec: consolev1alpha1.ConsoleSpec{ OperatorSpec: operatorsv1alpha1.OperatorSpec{ + // by default the console is managed ManagementState: "Managed", + // if Verison is not 4.0.0 our reconcile loop will not pick it up Version: "4.0.0", }, + // one replica is created Count: 1, }, } diff --git a/pkg/console/operator/sync_v400.go b/pkg/console/operator/sync_v400.go index 3e6956d..6a5e194 100644 --- a/pkg/console/operator/sync_v400.go +++ b/pkg/console/operator/sync_v400.go @@ -29,18 +29,13 @@ import ( servicesub "github.com/openshift/console-operator/pkg/console/subresource/service" ) -// runs the standard v4.0.0 reconcile loop -// the Apply logic is a bit tricky. -// - Default Route is incomplete, we expect the server to fill out host, -// so should not stomp on it after the initial run -// - other resources can be a tad tricky as well. func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1.Console, error) { - // aggregate the errors from this: + // aggregate allErrors := []error{} + // track changes, may triggler ripples & update consoleConfig.Status toUpdate := false - // apply service _, svcChanged, svcErr := resourceapply.ApplyService(co.serviceClient, servicesub.DefaultService(consoleConfig)) if svcErr != nil { @@ -52,11 +47,10 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1. // apply route - // TODO: - // - once we handle a custom hostname, upgrade to ApplyRoute() // - be sure to test that we don't trigger an infinite loop by stomping on the // default host name set by the server, or any other values. The ApplyRoute() // logic will have to be sound. + // - update to ApplyRoute() once the logic is settled rt, rtIsNew, rtErr := routesub.GetOrCreate(co.routeClient, routesub.DefaultRoute(consoleConfig)) // rt, rtChanged, rtErr := routesub.ApplyRoute(co.routeClient, routesub.DefaultRoute(consoleConfig)) if rtErr != nil { @@ -75,7 +69,7 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1. } toUpdate = toUpdate || cmChanged - // TODO: clean up the scoping here + // TODO: clean up, not fond of the scoping issues here // - the deployment needs to know about the change value in order to address updates, // but the wrapper is needed to avoid triggering loops unnecessarily secretChanged := false @@ -105,11 +99,8 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1. } - // TODO: deployment changes too much, dont trigger loop. - // the Apply() again is prob incorrect in that our DefaultDeploymnet() is - // too much... and there is prob something that gets stomped. - // apply deployment is a bit more involved as it needs information about version & if we should - // force a rollout of the pods. at this point, configMap updates are the bool for this + + // we don't want to thrash our deployment, but we also need to force rollout the pod whenever anything critical changes defaultDeployment := deploymentsub.DefaultDeployment(consoleConfig) versionAvailability := &operatorv1alpha1.VersionAvailability{ Version: consoleConfig.Spec.Version, @@ -124,17 +115,16 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1. } toUpdate = toUpdate || depChanged + // handy debugging block + //logrus.Printf("service changed: %v \n", svcChanged) + //logrus.Printf("route is new: %v \n", rtIsNew) + //logrus.Printf("configMap changed: %v \n", cmChanged) + //logrus.Printf("secret changed: %v \n", secretChanged) + //logrus.Printf("oauth changed: %v \n", oauthChanged) + //logrus.Printf("deployment changed: %v \n", depChanged) + //logrus.Println("------------") - - logrus.Printf("service changed: %v \n", svcChanged) - logrus.Printf("route is new: %v \n", rtIsNew) - logrus.Printf("configMap changed: %v \n", cmChanged) - logrus.Printf("secret changed: %v \n", secretChanged) - logrus.Printf("oauth changed: %v \n", oauthChanged) - logrus.Printf("deployment changed: %v \n", depChanged) - logrus.Println("------------") - - // if any of our resources have svcChanged, we should update the CR. otherwise, skip this step. + // if any of our resources have changed, we should update the consoleConfig.Status. otherwise, skip this step. if toUpdate { logrus.Infof("Sync_v400: To update Spec? %v", toUpdate) // TODO: set the status. @@ -178,9 +168,6 @@ func secretAndOauthMatch(secret *corev1.Secret, client *oauthv1.OAuthClient) boo // should be automatic so long as the CR.Status is // properly filled out with the appropriate values. func setStatus(cs v1alpha1.ConsoleStatus, svc *corev1.Service, rt *routev1.Route, cm *corev1.ConfigMap, dep *appsv1.Deployment, oa *oauthv1.OAuthClient, sec *corev1.Secret) { - logrus.Println("setStatus()") - logrus.Println("-----------") - // TODO: handle custom hosts as well if rt.Spec.Host != "" { cs.DefaultHostName = rt.Spec.Host diff --git a/pkg/console/subresource/configmap/configmap.go b/pkg/console/subresource/configmap/configmap.go index d26301d..5407417 100644 --- a/pkg/console/subresource/configmap/configmap.go +++ b/pkg/console/subresource/configmap/configmap.go @@ -6,7 +6,6 @@ import ( "github.com/openshift/console-operator/pkg/apis/console/v1alpha1" "github.com/openshift/console-operator/pkg/console/subresource/util" "github.com/openshift/console-operator/pkg/controller" - "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" corev1 "k8s.io/api/core/v1" ) @@ -25,15 +24,10 @@ const ( ) func DefaultConfigMap(cr *v1alpha1.Console, rt *v1.Route) *corev1.ConfigMap { + // NOTE: this should probably just take the route.Spec.Host string. + // without the host, the CR should not be created, it is essential for + // the deployment to be created correctly. if rt == nil { - // without a route, the configmap is useless. - // we should log, set the CR.status, and possibly create an Event - // if we can't create this. Its a big deal. - // (and update again once it's working) - // also, maybe we do get a route, but if it has no host, - // default or custom (or both or neither) then we need to - // handle cr.Status on that as well. That can be done - // in context of route, not here. return nil } host := rt.Spec.Host @@ -95,10 +89,11 @@ func servingInfo() yaml.MapSlice { } } -// TODO: take args as we update branding based on cluster config? func customization() yaml.MapSlice { return yaml.MapSlice{ { + // TODO: branding will need to be provided by higher level config. + // it should not be configurable in the CR, but needs to be configured somewhere. Key: "branding", Value: brandingDefault, }, { Key: "documentationBaseURL", Value: documentationBaseURL, @@ -106,7 +101,6 @@ func customization() yaml.MapSlice { } } -//// TODO: this can take args as we update locations after we generate a router func clusterInfo(host string) yaml.MapSlice { return yaml.MapSlice{ { @@ -114,9 +108,6 @@ func clusterInfo(host string) yaml.MapSlice { }, { Key: "consoleBasePath", Value: "", }, - // { - // Key: "masterPublicURL", Value: nil, - // }, } } @@ -125,7 +116,6 @@ func authServerYaml() yaml.MapSlice { return yaml.MapSlice{ { Key: "clientID", Value: controller.OpenShiftConsoleName, - // Key: "clientID", Value: OAuthClientName, }, { Key: "clientSecretFile", Value: clientSecretFilePath, }, { @@ -137,12 +127,7 @@ func authServerYaml() yaml.MapSlice { } func consoleBaseAddr(host string) string { - if host != "" { - str := fmt.Sprintf("https://%s", host) - logrus.Infof("console configmap base addr set to %v", str) - return str - } - return "" + return util.HTTPS(host) } diff --git a/pkg/console/subresource/deployment/deployment.go b/pkg/console/subresource/deployment/deployment.go index e19ffa1..c0359f8 100644 --- a/pkg/console/subresource/deployment/deployment.go +++ b/pkg/console/subresource/deployment/deployment.go @@ -24,8 +24,7 @@ type volumeConfig struct { name string readOnly bool path string - // defaultMode int - // will be either secret or configMap + // isSecret or isConfigMap are mutually exclusive isSecret bool isConfigMap bool } @@ -36,21 +35,18 @@ var volumeConfigList = []volumeConfig{ readOnly: true, path: "/var/serving-cert", isSecret: true, - // defaultMode: 288, }, { name: ConsoleOauthConfigName, readOnly: true, path: "/var/oauth-config", isSecret: true, - // defaultMode: 288, }, { name: "console-config", readOnly: true, path: "/var/console-config", isConfigMap: true, - // defaultMode: 288, }, } diff --git a/pkg/console/subresource/oauthclient/oauthclient.go b/pkg/console/subresource/oauthclient/oauthclient.go index dbbc7e3..9b7e180 100644 --- a/pkg/console/subresource/oauthclient/oauthclient.go +++ b/pkg/console/subresource/oauthclient/oauthclient.go @@ -1,22 +1,21 @@ package oauthclient import ( - "fmt" oauthv1 "github.com/openshift/api/oauth/v1" "github.com/openshift/api/route/v1" oauthclient "github.com/openshift/client-go/oauth/clientset/versioned/typed/oauth/v1" + "github.com/openshift/console-operator/pkg/console/subresource/util" "github.com/openshift/console-operator/pkg/controller" "github.com/openshift/console-operator/pkg/crypto" "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" - "github.com/sirupsen/logrus" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "strings" ) // TODO: ApplyOauth should be a generic Apply that could be used for any oauth-client -// - should look like resourceapply.ApplyService -// - perhaps should be PR'd to client-go +// - should look like resourceapply.ApplyService and the other Apply funcs +// once its in a trustworthy state, PR to library-go so it can live with +// the other Apply funcs func ApplyOAuth(client oauthclient.OAuthClientsGetter, required *oauthv1.OAuthClient) (*oauthv1.OAuthClient, bool, error) { existing, err := client.OAuthClients().Get(required.Name, metav1.GetOptions{}) if apierrors.IsNotFound(err) { @@ -49,18 +48,17 @@ func RegisterConsoleToOAuthClient(client *oauthv1.OAuthClient, route *v1.Route, if route == nil { return nil } - // we should be the only ones using this client, so we can - // stomp all over existing RedirectURIs. - // TODO: potentially support multiple if multiple routes service - // the console + // we are the only application for this client + // in the future we may accept multiple routes client.RedirectURIs = []string{} - client.RedirectURIs = append(client.RedirectURIs, https(route.Spec.Host)) + client.RedirectURIs = append(client.RedirectURIs, util.HTTPS(route.Spec.Host)) // client.Secret = randomBits client.Secret = string(randomBits) return client } // for ManagementState.Removed +// Console does not have create/delete priviledges on oauth clients, only update func DeRegisterConsoleFromOAuthClient(client *oauthv1.OAuthClient) *oauthv1.OAuthClient { client.RedirectURIs = []string{} // changing the string to anything else will invalidate the client @@ -68,18 +66,12 @@ func DeRegisterConsoleFromOAuthClient(client *oauthv1.OAuthClient) *oauthv1.OAut return client } -// cr *v1alpha1.Console, rt *v1.Route -// the OAuthClient is a cluster scoped resource that will be stamped -// out on install by the CVO. We know for certain we will not create -// this, so there is no point in fleshing out its values here, unlike -// the other resources we are responsible for. func DefaultOauthClient() *oauthv1.OAuthClient{ - // we cannot set an ownerRef on the OAuthClient as it is - // a cluster scoped resource. return Stub() } func Stub() *oauthv1.OAuthClient{ + // we cannot set an ownerRef on the OAuthClient as it is cluster scoped return &oauthv1.OAuthClient{ ObjectMeta: metav1.ObjectMeta{ Name: controller.OpenShiftConsoleName, @@ -87,21 +79,6 @@ func Stub() *oauthv1.OAuthClient{ } } -// TODO: technically, this should take targetPort from route.spec.port.targetPort -func https(host string) string { - protocol := "https://" - if host == "" { - logrus.Infof("host is invalid empty string") - return "" - } - if strings.HasPrefix(host, protocol) { - return host - } - secured := fmt.Sprintf("%s%s", protocol, host) - logrus.Infof("host updated from %s to %s", host, secured) - return secured -} - func GetSecretString(client *oauthv1.OAuthClient) string { return client.Secret } diff --git a/pkg/console/subresource/route/route.go b/pkg/console/subresource/route/route.go index fc440dd..9108045 100644 --- a/pkg/console/subresource/route/route.go +++ b/pkg/console/subresource/route/route.go @@ -16,7 +16,8 @@ import ( "github.com/openshift/console-operator/pkg/controller" ) -// this is a stop gap for now. we want ApplyRoute correct, but don't need it yet +// We can't blindly ApplyRoute() as we need the server to annotate the +// route.Spec.Host, so we need this func func GetOrCreate(client routeclient.RoutesGetter, required *routev1.Route) (*routev1.Route, bool, error) { isNew := false existing, err := client.Routes(required.Namespace).Get(required.Name, metav1.GetOptions{}) @@ -32,8 +33,9 @@ func GetOrCreate(client routeclient.RoutesGetter, required *routev1.Route) (*rou } // TODO: ApplyRoute -// - should look like resourceapply.ApplyService -// - should be PR'd to client-go +// - Handle the nuance of ApplyRoute(), noting that Host and perhaps other +// fields are provided later by the server. Once we know its correct, +// PR to library-go so it can live with the other Apply* funcs func ApplyRoute(client routeclient.RoutesGetter, required *routev1.Route) (*routev1.Route, bool, error) { // first, get or create existing, err := client.Routes(required.Namespace).Get(required.Name, metav1.GetOptions{}) @@ -48,7 +50,7 @@ func ApplyRoute(client routeclient.RoutesGetter, required *routev1.Route) (*rout modified := resourcemerge.BoolPtr(false) resourcemerge.EnsureObjectMeta(modified, &existing.ObjectMeta, required.ObjectMeta) - // possibly this should just be a DeepEqual on Spec... + // possibly this should just be a DeepEqual on Spec? hostSame := equality.Semantic.DeepEqual(existing.Spec.Host, required.Spec.Host) portSame := equality.Semantic.DeepEqual(existing.Spec.Port, required.Spec.Port) tlsSame := equality.Semantic.DeepEqual(existing.Spec.TLS, required.Spec.TLS) diff --git a/pkg/console/subresource/secret/secret.go b/pkg/console/subresource/secret/secret.go index 2bcd43c..4cf0524 100644 --- a/pkg/console/subresource/secret/secret.go +++ b/pkg/console/subresource/secret/secret.go @@ -17,7 +17,7 @@ func DefaultSecret(cr *v1alpha1.Console, randomBits string) *corev1.Secret { logrus.Printf("DefaultSecret() %v", randomBits) secret := Stub() - // TODO: open bug in client-go, it drops StringData :/ + // TODO: client-go ignores the StringData field. Open a PR to fix this //secret.StringData = map[string]string{ // ClientSecretKey: randomBits, //} diff --git a/pkg/console/subresource/service/service.go b/pkg/console/subresource/service/service.go index e1a5b67..8fe615c 100644 --- a/pkg/console/subresource/service/service.go +++ b/pkg/console/subresource/service/service.go @@ -9,12 +9,11 @@ import ( ) const ( - // this annotation should generate us a certificate + // this annotation should generate us a serving certificate ServingCertSecretAnnotation = "service.alpha.openshift.io/serving-cert-secret-name" ) const ( - // perhaps move ConsoleServingCertName = "console-serving-cert" consolePortName = "https" consolePort = 443 diff --git a/pkg/console/subresource/util/util.go b/pkg/console/subresource/util/util.go index f708cec..9ce8247 100644 --- a/pkg/console/subresource/util/util.go +++ b/pkg/console/subresource/util/util.go @@ -9,6 +9,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "os" + "strings" ) func SharedLabels() map[string]string { @@ -63,6 +64,8 @@ func AddOwnerRef(obj v1.Object, ownerRef *v1.OwnerReference) { //} } +// func RemoveOwnerRef + func OwnerRefFrom(cr *v1alpha1.Console) *v1.OwnerReference { if cr != nil { truthy := true @@ -82,3 +85,19 @@ func OwnerRefFrom(cr *v1alpha1.Console) *v1.OwnerReference { func GetImageEnv() string { return os.Getenv("IMAGE") } + +// TODO: technically, this should take targetPort from route.spec.port.targetPort +func HTTPS(host string) string { + protocol := "https://" + if host == "" { + logrus.Infof("util.HTTPS() cannot accept an empty string.") + return "" + } + if strings.HasPrefix(host, protocol) { + return host + } + secured := fmt.Sprintf("%s%s", protocol, host) + logrus.Infof("util.HTTPS(): from %s to %s", host, secured) + return secured +} + diff --git a/pkg/console/version/version.go b/pkg/console/version/version.go index 03fd54b..8793f42 100644 --- a/pkg/console/version/version.go +++ b/pkg/console/version/version.go @@ -36,8 +36,8 @@ func Get() version.Info { func init() { buildInfo := prometheus.NewGaugeVec( prometheus.GaugeOpts{ - Name: "openshift_service_serving_cert_signer_build_info", - Help: "A metric with a constant '1' value labeled by major, minor, git commit & git version from which OpenShift Service Serving Cert Signer was built.", + Name: "openshift_console_operator_build_info", + Help: "A metric with a constant '1' value labeled by major, minor, git commit & git version from which OpenShift Console Operator was built.", }, []string{"major", "minor", "gitCommit", "gitVersion"}, ) From d59d60c84caba0ee5e7e24c3b1dee24b83ea2cf5 Mon Sep 17 00:00:00 2001 From: "Benjamin A. Petersen" Date: Tue, 20 Nov 2018 22:14:34 -0500 Subject: [PATCH 24/24] f --- pkg/console/operator/sync_v400.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/console/operator/sync_v400.go b/pkg/console/operator/sync_v400.go index 6a5e194..766abb8 100644 --- a/pkg/console/operator/sync_v400.go +++ b/pkg/console/operator/sync_v400.go @@ -73,7 +73,7 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1. // - the deployment needs to know about the change value in order to address updates, // but the wrapper is needed to avoid triggering loops unnecessarily secretChanged := false - oauthChanged := false + // oauthChanged := false if !secretsMatch(co.secretsClient, co.oauthClient) { // shared secret bits // sharedOAuthSecretBits := crypto.RandomBits(256) @@ -96,7 +96,6 @@ func sync_v400(co *ConsoleOperator, consoleConfig *v1alpha1.Console) (*v1alpha1. allErrors = append(allErrors, secErr) } toUpdate = toUpdate || secretChanged - }