This is an automated email from the ASF dual-hosted git repository.

hanahmily pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking-swck.git

commit 8d7d8f7a6c83a78a7a28722da787c6531be12604
Author: Gao Hongtao <hanahm...@gmail.com>
AuthorDate: Wed Feb 26 11:16:09 2020 +0800

    Add OAP Server CRDs
    
    Signed-off-by: Gao Hongtao <hanahm...@gmail.com>
---
 PROJECT                                            |   4 +
 api/v1alpha1/groupversion_info.go                  |  37 ++
 api/v1alpha1/oapserver_types.go                    |  99 +++
 api/v1alpha1/zz_generated.deepcopy.go              | 151 +++++
 .../operator.skywalking.apache.org_oapservers.yaml | 721 +++++++++++++++++++++
 config/crd/kustomization.yaml                      |  21 +
 config/crd/kustomizeconfig.yaml                    |  17 +
 config/crd/patches/cainjection_in_oapservers.yaml  |   8 +
 config/crd/patches/webhook_in_oapservers.yaml      |  17 +
 config/rbac/oapserver_editor_role.yaml             |  24 +
 config/rbac/oapserver_viewer_role.yaml             |  20 +
 config/rbac/role.yaml                              |  28 +
 config/webhook/manifests.yaml                      |   0
 controllers/oapserver_controller.go                |  54 ++
 controllers/suite_test.go                          |  81 +++
 go.mod                                             |   4 +
 main.go                                            |  12 +
 17 files changed, 1298 insertions(+)

diff --git a/PROJECT b/PROJECT
index 0b30de2..e04083d 100644
--- a/PROJECT
+++ b/PROJECT
@@ -1,3 +1,7 @@
 domain: skywalking.apache.org
 repo: github.com/skywalking-swck
+resources:
+- group: operator
+  kind: OAPServer
+  version: v1alpha1
 version: "2"
diff --git a/api/v1alpha1/groupversion_info.go 
b/api/v1alpha1/groupversion_info.go
new file mode 100644
index 0000000..cba2eb5
--- /dev/null
+++ b/api/v1alpha1/groupversion_info.go
@@ -0,0 +1,37 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// Package v1alpha1 contains API Schema definitions for the operator v1alpha1 
API group
+// +kubebuilder:object:generate=true
+// +groupName=operator.skywalking.apache.org
+package v1alpha1
+
+import (
+       "k8s.io/apimachinery/pkg/runtime/schema"
+       "sigs.k8s.io/controller-runtime/pkg/scheme"
+)
+
+var (
+       // GroupVersion is group version used to register these objects
+       GroupVersion = schema.GroupVersion{Group: 
"operator.skywalking.apache.org", Version: "v1alpha1"}
+
+       // SchemeBuilder is used to add go types to the GroupVersionKind scheme
+       SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
+
+       // AddToScheme adds the types in this group-version to the given scheme.
+       AddToScheme = SchemeBuilder.AddToScheme
+)
diff --git a/api/v1alpha1/oapserver_types.go b/api/v1alpha1/oapserver_types.go
new file mode 100644
index 0000000..6773111
--- /dev/null
+++ b/api/v1alpha1/oapserver_types.go
@@ -0,0 +1,99 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package v1alpha1
+
+import (
+       corev1 "k8s.io/api/core/v1"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// OAPServerSpec defines the desired state of OAPServer
+type OAPServerSpec struct {
+       // Version of OAP.
+       Version string `json:"version"`
+       // Image is the OAP Server Docker image to deploy.
+       Image string `json:"image,omitempty"`
+       // Count is the number of OAP servers
+       Instances int `json:"instances,imitempty"`
+       // Config holds the OAP server configuration.
+       Config map[string]string `json:"config,omitempty"`
+
+       // NodeSelector is a selector which must be true for the pod to fit on 
a node.
+       // Selector which must match a node's labels for the pod to be 
scheduled on that node.
+       // More info: 
https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
+       // +kubebuilder:validation:Optional
+       NodeSelector map[string]string `json:"nodeSelector,omitempty"`
+       // If specified, affinity will define the pod's scheduling constraints
+       // +kubebuilder:validation:Optional
+       Affinity *corev1.Affinity `json:"affinity,omitempty"`
+       // Tolerations allows specifying a list of tolerations for controlling 
which
+       // set of Nodes a Pod can be scheduled on
+       // +kubebuilder:validation:Optional
+       Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"`
+       // Resources holds ResourceRequirements for the OAP server containers
+       // +kubebuilder:validation:Optional
+       Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
+}
+
+// OAPServerPhase is the phase OAP server is in from the controller point of 
view.
+type OAPServerPhase string
+
+const (
+       // OAPServerReadyPhase is operating at the desired spec.
+       OAPServerReadyPhase OAPServerPhase = "Ready"
+       // OAPServerChangingPhase controller is working towards a desired 
state, cluster can be unavailable.
+       OAPServerChangingPhase OAPServerPhase = "Changing"
+       // OAPServerResourceInvalid is marking a resource as invalid, should 
never happen if admission control is installed correctly.
+       OAPServerResourceInvalid OAPServerPhase = "Invalid"
+)
+
+// OAPServerStatus defines the observed state of OAPServer
+type OAPServerStatus struct {
+       // The phase OAP servers is in.
+       Phase OAPServerPhase `json:"phase,omitempty"`
+       // A human readable message indicating details about why the OAP 
servers is in this phase.
+       // +kubebuilder:validation:Optional
+       Message string `json:"message,omitempty"`
+       // A brief CamelCase message indicating details about why the OAP 
servers is in this state.
+       // +kubebuilder:validation:Optional
+       Reason string `json:"reason,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// OAPServer is the Schema for the oapservers API
+type OAPServer struct {
+       metav1.TypeMeta   `json:",inline"`
+       metav1.ObjectMeta `json:"metadata,omitempty"`
+
+       Spec   OAPServerSpec   `json:"spec,omitempty"`
+       Status OAPServerStatus `json:"status,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// OAPServerList contains a list of OAPServer
+type OAPServerList struct {
+       metav1.TypeMeta `json:",inline"`
+       metav1.ListMeta `json:"metadata,omitempty"`
+       Items           []OAPServer `json:"items"`
+}
+
+func init() {
+       SchemeBuilder.Register(&OAPServer{}, &OAPServerList{})
+}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go 
b/api/v1alpha1/zz_generated.deepcopy.go
new file mode 100644
index 0000000..80f4197
--- /dev/null
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -0,0 +1,151 @@
+// +build !ignore_autogenerated
+
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// Code generated by controller-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+       "k8s.io/api/core/v1"
+       runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *OAPServer) DeepCopyInto(out *OAPServer) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+       in.Spec.DeepCopyInto(&out.Spec)
+       out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new OAPServer.
+func (in *OAPServer) DeepCopy() *OAPServer {
+       if in == nil {
+               return nil
+       }
+       out := new(OAPServer)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, 
creating a new runtime.Object.
+func (in *OAPServer) DeepCopyObject() runtime.Object {
+       if c := in.DeepCopy(); c != nil {
+               return c
+       }
+       return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *OAPServerList) DeepCopyInto(out *OAPServerList) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ListMeta.DeepCopyInto(&out.ListMeta)
+       if in.Items != nil {
+               in, out := &in.Items, &out.Items
+               *out = make([]OAPServer, len(*in))
+               for i := range *in {
+                       (*in)[i].DeepCopyInto(&(*out)[i])
+               }
+       }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new OAPServerList.
+func (in *OAPServerList) DeepCopy() *OAPServerList {
+       if in == nil {
+               return nil
+       }
+       out := new(OAPServerList)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, 
creating a new runtime.Object.
+func (in *OAPServerList) DeepCopyObject() runtime.Object {
+       if c := in.DeepCopy(); c != nil {
+               return c
+       }
+       return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *OAPServerSpec) DeepCopyInto(out *OAPServerSpec) {
+       *out = *in
+       if in.Config != nil {
+               in, out := &in.Config, &out.Config
+               *out = make(map[string]string, len(*in))
+               for key, val := range *in {
+                       (*out)[key] = val
+               }
+       }
+       if in.NodeSelector != nil {
+               in, out := &in.NodeSelector, &out.NodeSelector
+               *out = make(map[string]string, len(*in))
+               for key, val := range *in {
+                       (*out)[key] = val
+               }
+       }
+       if in.Affinity != nil {
+               in, out := &in.Affinity, &out.Affinity
+               *out = new(v1.Affinity)
+               (*in).DeepCopyInto(*out)
+       }
+       if in.Tolerations != nil {
+               in, out := &in.Tolerations, &out.Tolerations
+               *out = new([]v1.Toleration)
+               if **in != nil {
+                       in, out := *in, *out
+                       *out = make([]v1.Toleration, len(*in))
+                       for i := range *in {
+                               (*in)[i].DeepCopyInto(&(*out)[i])
+                       }
+               }
+       }
+       if in.Resources != nil {
+               in, out := &in.Resources, &out.Resources
+               *out = new(v1.ResourceRequirements)
+               (*in).DeepCopyInto(*out)
+       }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new OAPServerSpec.
+func (in *OAPServerSpec) DeepCopy() *OAPServerSpec {
+       if in == nil {
+               return nil
+       }
+       out := new(OAPServerSpec)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *OAPServerStatus) DeepCopyInto(out *OAPServerStatus) {
+       *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new OAPServerStatus.
+func (in *OAPServerStatus) DeepCopy() *OAPServerStatus {
+       if in == nil {
+               return nil
+       }
+       out := new(OAPServerStatus)
+       in.DeepCopyInto(out)
+       return out
+}
diff --git a/config/crd/bases/operator.skywalking.apache.org_oapservers.yaml 
b/config/crd/bases/operator.skywalking.apache.org_oapservers.yaml
new file mode 100644
index 0000000..42525f7
--- /dev/null
+++ b/config/crd/bases/operator.skywalking.apache.org_oapservers.yaml
@@ -0,0 +1,721 @@
+
+---
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.2.4
+  creationTimestamp: null
+  name: oapservers.operator.skywalking.apache.org
+spec:
+  group: operator.skywalking.apache.org
+  names:
+    kind: OAPServer
+    listKind: OAPServerList
+    plural: oapservers
+    singular: oapserver
+  scope: Namespaced
+  validation:
+    openAPIV3Schema:
+      description: OAPServer is the Schema for the oapservers API
+      properties:
+        apiVersion:
+          description: 'APIVersion defines the versioned schema of this 
representation
+            of an object. Servers should convert recognized schemas to the 
latest
+            internal value, and may reject unrecognized values. More info: 
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+          type: string
+        kind:
+          description: 'Kind is a string value representing the REST resource 
this
+            object represents. Servers may infer this from the endpoint the 
client
+            submits requests to. Cannot be updated. In CamelCase. More info: 
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+          type: string
+        metadata:
+          type: object
+        spec:
+          description: OAPServerSpec defines the desired state of OAPServer
+          properties:
+            affinity:
+              description: If specified, affinity will define the pod's 
scheduling
+                constraints
+              properties:
+                nodeAffinity:
+                  description: Describes node affinity scheduling rules for 
the pod.
+                  properties:
+                    preferredDuringSchedulingIgnoredDuringExecution:
+                      description: The scheduler will prefer to schedule pods 
to nodes
+                        that satisfy the affinity expressions specified by 
this field,
+                        but it may choose a node that violates one or more of 
the
+                        expressions. The node that is most preferred is the 
one with
+                        the greatest sum of weights, i.e. for each node that 
meets
+                        all of the scheduling requirements (resource request, 
requiredDuringScheduling
+                        affinity expressions, etc.), compute a sum by 
iterating through
+                        the elements of this field and adding "weight" to the 
sum
+                        if the node matches the corresponding 
matchExpressions; the
+                        node(s) with the highest sum are the most preferred.
+                      items:
+                        description: An empty preferred scheduling term 
matches all
+                          objects with implicit weight 0 (i.e. it's a no-op). 
A null
+                          preferred scheduling term matches no objects (i.e. 
is also
+                          a no-op).
+                        properties:
+                          preference:
+                            description: A node selector term, associated with 
the
+                              corresponding weight.
+                            properties:
+                              matchExpressions:
+                                description: A list of node selector 
requirements
+                                  by node's labels.
+                                items:
+                                  description: A node selector requirement is 
a selector
+                                    that contains values, a key, and an 
operator that
+                                    relates the key and values.
+                                  properties:
+                                    key:
+                                      description: The label key that the 
selector
+                                        applies to.
+                                      type: string
+                                    operator:
+                                      description: Represents a key's 
relationship
+                                        to a set of values. Valid operators 
are In,
+                                        NotIn, Exists, DoesNotExist. Gt, and 
Lt.
+                                      type: string
+                                    values:
+                                      description: An array of string values. 
If the
+                                        operator is In or NotIn, the values 
array
+                                        must be non-empty. If the operator is 
Exists
+                                        or DoesNotExist, the values array must 
be
+                                        empty. If the operator is Gt or Lt, 
the values
+                                        array must have a single element, 
which will
+                                        be interpreted as an integer. This 
array is
+                                        replaced during a strategic merge 
patch.
+                                      items:
+                                        type: string
+                                      type: array
+                                  required:
+                                  - key
+                                  - operator
+                                  type: object
+                                type: array
+                              matchFields:
+                                description: A list of node selector 
requirements
+                                  by node's fields.
+                                items:
+                                  description: A node selector requirement is 
a selector
+                                    that contains values, a key, and an 
operator that
+                                    relates the key and values.
+                                  properties:
+                                    key:
+                                      description: The label key that the 
selector
+                                        applies to.
+                                      type: string
+                                    operator:
+                                      description: Represents a key's 
relationship
+                                        to a set of values. Valid operators 
are In,
+                                        NotIn, Exists, DoesNotExist. Gt, and 
Lt.
+                                      type: string
+                                    values:
+                                      description: An array of string values. 
If the
+                                        operator is In or NotIn, the values 
array
+                                        must be non-empty. If the operator is 
Exists
+                                        or DoesNotExist, the values array must 
be
+                                        empty. If the operator is Gt or Lt, 
the values
+                                        array must have a single element, 
which will
+                                        be interpreted as an integer. This 
array is
+                                        replaced during a strategic merge 
patch.
+                                      items:
+                                        type: string
+                                      type: array
+                                  required:
+                                  - key
+                                  - operator
+                                  type: object
+                                type: array
+                            type: object
+                          weight:
+                            description: Weight associated with matching the 
corresponding
+                              nodeSelectorTerm, in the range 1-100.
+                            format: int32
+                            type: integer
+                        required:
+                        - preference
+                        - weight
+                        type: object
+                      type: array
+                    requiredDuringSchedulingIgnoredDuringExecution:
+                      description: If the affinity requirements specified by 
this
+                        field are not met at scheduling time, the pod will not 
be
+                        scheduled onto the node. If the affinity requirements 
specified
+                        by this field cease to be met at some point during pod 
execution
+                        (e.g. due to an update), the system may or may not try 
to
+                        eventually evict the pod from its node.
+                      properties:
+                        nodeSelectorTerms:
+                          description: Required. A list of node selector 
terms. The
+                            terms are ORed.
+                          items:
+                            description: A null or empty node selector term 
matches
+                              no objects. The requirements of them are ANDed. 
The
+                              TopologySelectorTerm type implements a subset of 
the
+                              NodeSelectorTerm.
+                            properties:
+                              matchExpressions:
+                                description: A list of node selector 
requirements
+                                  by node's labels.
+                                items:
+                                  description: A node selector requirement is 
a selector
+                                    that contains values, a key, and an 
operator that
+                                    relates the key and values.
+                                  properties:
+                                    key:
+                                      description: The label key that the 
selector
+                                        applies to.
+                                      type: string
+                                    operator:
+                                      description: Represents a key's 
relationship
+                                        to a set of values. Valid operators 
are In,
+                                        NotIn, Exists, DoesNotExist. Gt, and 
Lt.
+                                      type: string
+                                    values:
+                                      description: An array of string values. 
If the
+                                        operator is In or NotIn, the values 
array
+                                        must be non-empty. If the operator is 
Exists
+                                        or DoesNotExist, the values array must 
be
+                                        empty. If the operator is Gt or Lt, 
the values
+                                        array must have a single element, 
which will
+                                        be interpreted as an integer. This 
array is
+                                        replaced during a strategic merge 
patch.
+                                      items:
+                                        type: string
+                                      type: array
+                                  required:
+                                  - key
+                                  - operator
+                                  type: object
+                                type: array
+                              matchFields:
+                                description: A list of node selector 
requirements
+                                  by node's fields.
+                                items:
+                                  description: A node selector requirement is 
a selector
+                                    that contains values, a key, and an 
operator that
+                                    relates the key and values.
+                                  properties:
+                                    key:
+                                      description: The label key that the 
selector
+                                        applies to.
+                                      type: string
+                                    operator:
+                                      description: Represents a key's 
relationship
+                                        to a set of values. Valid operators 
are In,
+                                        NotIn, Exists, DoesNotExist. Gt, and 
Lt.
+                                      type: string
+                                    values:
+                                      description: An array of string values. 
If the
+                                        operator is In or NotIn, the values 
array
+                                        must be non-empty. If the operator is 
Exists
+                                        or DoesNotExist, the values array must 
be
+                                        empty. If the operator is Gt or Lt, 
the values
+                                        array must have a single element, 
which will
+                                        be interpreted as an integer. This 
array is
+                                        replaced during a strategic merge 
patch.
+                                      items:
+                                        type: string
+                                      type: array
+                                  required:
+                                  - key
+                                  - operator
+                                  type: object
+                                type: array
+                            type: object
+                          type: array
+                      required:
+                      - nodeSelectorTerms
+                      type: object
+                  type: object
+                podAffinity:
+                  description: Describes pod affinity scheduling rules (e.g. 
co-locate
+                    this pod in the same node, zone, etc. as some other 
pod(s)).
+                  properties:
+                    preferredDuringSchedulingIgnoredDuringExecution:
+                      description: The scheduler will prefer to schedule pods 
to nodes
+                        that satisfy the affinity expressions specified by 
this field,
+                        but it may choose a node that violates one or more of 
the
+                        expressions. The node that is most preferred is the 
one with
+                        the greatest sum of weights, i.e. for each node that 
meets
+                        all of the scheduling requirements (resource request, 
requiredDuringScheduling
+                        affinity expressions, etc.), compute a sum by 
iterating through
+                        the elements of this field and adding "weight" to the 
sum
+                        if the node has pods which matches the corresponding 
podAffinityTerm;
+                        the node(s) with the highest sum are the most 
preferred.
+                      items:
+                        description: The weights of all of the matched 
WeightedPodAffinityTerm
+                          fields are added per-node to find the most preferred 
node(s)
+                        properties:
+                          podAffinityTerm:
+                            description: Required. A pod affinity term, 
associated
+                              with the corresponding weight.
+                            properties:
+                              labelSelector:
+                                description: A label query over a set of 
resources,
+                                  in this case pods.
+                                properties:
+                                  matchExpressions:
+                                    description: matchExpressions is a list of 
label
+                                      selector requirements. The requirements 
are
+                                      ANDed.
+                                    items:
+                                      description: A label selector 
requirement is
+                                        a selector that contains values, a 
key, and
+                                        an operator that relates the key and 
values.
+                                      properties:
+                                        key:
+                                          description: key is the label key 
that the
+                                            selector applies to.
+                                          type: string
+                                        operator:
+                                          description: operator represents a 
key's
+                                            relationship to a set of values. 
Valid
+                                            operators are In, NotIn, Exists 
and DoesNotExist.
+                                          type: string
+                                        values:
+                                          description: values is an array of 
string
+                                            values. If the operator is In or 
NotIn,
+                                            the values array must be 
non-empty. If
+                                            the operator is Exists or 
DoesNotExist,
+                                            the values array must be empty. 
This array
+                                            is replaced during a strategic 
merge patch.
+                                          items:
+                                            type: string
+                                          type: array
+                                      required:
+                                      - key
+                                      - operator
+                                      type: object
+                                    type: array
+                                  matchLabels:
+                                    additionalProperties:
+                                      type: string
+                                    description: matchLabels is a map of 
{key,value}
+                                      pairs. A single {key,value} in the 
matchLabels
+                                      map is equivalent to an element of 
matchExpressions,
+                                      whose key field is "key", the operator 
is "In",
+                                      and the values array contains only 
"value".
+                                      The requirements are ANDed.
+                                    type: object
+                                type: object
+                              namespaces:
+                                description: namespaces specifies which 
namespaces
+                                  the labelSelector applies to (matches 
against);
+                                  null or empty list means "this pod's 
namespace"
+                                items:
+                                  type: string
+                                type: array
+                              topologyKey:
+                                description: This pod should be co-located 
(affinity)
+                                  or not co-located (anti-affinity) with the 
pods
+                                  matching the labelSelector in the specified 
namespaces,
+                                  where co-located is defined as running on a 
node
+                                  whose value of the label with key 
topologyKey matches
+                                  that of any node on which any of the 
selected pods
+                                  is running. Empty topologyKey is not allowed.
+                                type: string
+                            required:
+                            - topologyKey
+                            type: object
+                          weight:
+                            description: weight associated with matching the 
corresponding
+                              podAffinityTerm, in the range 1-100.
+                            format: int32
+                            type: integer
+                        required:
+                        - podAffinityTerm
+                        - weight
+                        type: object
+                      type: array
+                    requiredDuringSchedulingIgnoredDuringExecution:
+                      description: If the affinity requirements specified by 
this
+                        field are not met at scheduling time, the pod will not 
be
+                        scheduled onto the node. If the affinity requirements 
specified
+                        by this field cease to be met at some point during pod 
execution
+                        (e.g. due to a pod label update), the system may or 
may not
+                        try to eventually evict the pod from its node. When 
there
+                        are multiple elements, the lists of nodes 
corresponding to
+                        each podAffinityTerm are intersected, i.e. all terms 
must
+                        be satisfied.
+                      items:
+                        description: Defines a set of pods (namely those 
matching
+                          the labelSelector relative to the given 
namespace(s)) that
+                          this pod should be co-located (affinity) or not 
co-located
+                          (anti-affinity) with, where co-located is defined as 
running
+                          on a node whose value of the label with key 
<topologyKey>
+                          matches that of any node on which a pod of the set 
of pods
+                          is running
+                        properties:
+                          labelSelector:
+                            description: A label query over a set of 
resources, in
+                              this case pods.
+                            properties:
+                              matchExpressions:
+                                description: matchExpressions is a list of 
label selector
+                                  requirements. The requirements are ANDed.
+                                items:
+                                  description: A label selector requirement is 
a selector
+                                    that contains values, a key, and an 
operator that
+                                    relates the key and values.
+                                  properties:
+                                    key:
+                                      description: key is the label key that 
the selector
+                                        applies to.
+                                      type: string
+                                    operator:
+                                      description: operator represents a key's 
relationship
+                                        to a set of values. Valid operators 
are In,
+                                        NotIn, Exists and DoesNotExist.
+                                      type: string
+                                    values:
+                                      description: values is an array of 
string values.
+                                        If the operator is In or NotIn, the 
values
+                                        array must be non-empty. If the 
operator is
+                                        Exists or DoesNotExist, the values 
array must
+                                        be empty. This array is replaced 
during a
+                                        strategic merge patch.
+                                      items:
+                                        type: string
+                                      type: array
+                                  required:
+                                  - key
+                                  - operator
+                                  type: object
+                                type: array
+                              matchLabels:
+                                additionalProperties:
+                                  type: string
+                                description: matchLabels is a map of 
{key,value} pairs.
+                                  A single {key,value} in the matchLabels map 
is equivalent
+                                  to an element of matchExpressions, whose key 
field
+                                  is "key", the operator is "In", and the 
values array
+                                  contains only "value". The requirements are 
ANDed.
+                                type: object
+                            type: object
+                          namespaces:
+                            description: namespaces specifies which namespaces 
the
+                              labelSelector applies to (matches against); null 
or
+                              empty list means "this pod's namespace"
+                            items:
+                              type: string
+                            type: array
+                          topologyKey:
+                            description: This pod should be co-located 
(affinity)
+                              or not co-located (anti-affinity) with the pods 
matching
+                              the labelSelector in the specified namespaces, 
where
+                              co-located is defined as running on a node whose 
value
+                              of the label with key topologyKey matches that 
of any
+                              node on which any of the selected pods is 
running. Empty
+                              topologyKey is not allowed.
+                            type: string
+                        required:
+                        - topologyKey
+                        type: object
+                      type: array
+                  type: object
+                podAntiAffinity:
+                  description: Describes pod anti-affinity scheduling rules 
(e.g.
+                    avoid putting this pod in the same node, zone, etc. as 
some other
+                    pod(s)).
+                  properties:
+                    preferredDuringSchedulingIgnoredDuringExecution:
+                      description: The scheduler will prefer to schedule pods 
to nodes
+                        that satisfy the anti-affinity expressions specified 
by this
+                        field, but it may choose a node that violates one or 
more
+                        of the expressions. The node that is most preferred is 
the
+                        one with the greatest sum of weights, i.e. for each 
node that
+                        meets all of the scheduling requirements (resource 
request,
+                        requiredDuringScheduling anti-affinity expressions, 
etc.),
+                        compute a sum by iterating through the elements of 
this field
+                        and adding "weight" to the sum if the node has pods 
which
+                        matches the corresponding podAffinityTerm; the node(s) 
with
+                        the highest sum are the most preferred.
+                      items:
+                        description: The weights of all of the matched 
WeightedPodAffinityTerm
+                          fields are added per-node to find the most preferred 
node(s)
+                        properties:
+                          podAffinityTerm:
+                            description: Required. A pod affinity term, 
associated
+                              with the corresponding weight.
+                            properties:
+                              labelSelector:
+                                description: A label query over a set of 
resources,
+                                  in this case pods.
+                                properties:
+                                  matchExpressions:
+                                    description: matchExpressions is a list of 
label
+                                      selector requirements. The requirements 
are
+                                      ANDed.
+                                    items:
+                                      description: A label selector 
requirement is
+                                        a selector that contains values, a 
key, and
+                                        an operator that relates the key and 
values.
+                                      properties:
+                                        key:
+                                          description: key is the label key 
that the
+                                            selector applies to.
+                                          type: string
+                                        operator:
+                                          description: operator represents a 
key's
+                                            relationship to a set of values. 
Valid
+                                            operators are In, NotIn, Exists 
and DoesNotExist.
+                                          type: string
+                                        values:
+                                          description: values is an array of 
string
+                                            values. If the operator is In or 
NotIn,
+                                            the values array must be 
non-empty. If
+                                            the operator is Exists or 
DoesNotExist,
+                                            the values array must be empty. 
This array
+                                            is replaced during a strategic 
merge patch.
+                                          items:
+                                            type: string
+                                          type: array
+                                      required:
+                                      - key
+                                      - operator
+                                      type: object
+                                    type: array
+                                  matchLabels:
+                                    additionalProperties:
+                                      type: string
+                                    description: matchLabels is a map of 
{key,value}
+                                      pairs. A single {key,value} in the 
matchLabels
+                                      map is equivalent to an element of 
matchExpressions,
+                                      whose key field is "key", the operator 
is "In",
+                                      and the values array contains only 
"value".
+                                      The requirements are ANDed.
+                                    type: object
+                                type: object
+                              namespaces:
+                                description: namespaces specifies which 
namespaces
+                                  the labelSelector applies to (matches 
against);
+                                  null or empty list means "this pod's 
namespace"
+                                items:
+                                  type: string
+                                type: array
+                              topologyKey:
+                                description: This pod should be co-located 
(affinity)
+                                  or not co-located (anti-affinity) with the 
pods
+                                  matching the labelSelector in the specified 
namespaces,
+                                  where co-located is defined as running on a 
node
+                                  whose value of the label with key 
topologyKey matches
+                                  that of any node on which any of the 
selected pods
+                                  is running. Empty topologyKey is not allowed.
+                                type: string
+                            required:
+                            - topologyKey
+                            type: object
+                          weight:
+                            description: weight associated with matching the 
corresponding
+                              podAffinityTerm, in the range 1-100.
+                            format: int32
+                            type: integer
+                        required:
+                        - podAffinityTerm
+                        - weight
+                        type: object
+                      type: array
+                    requiredDuringSchedulingIgnoredDuringExecution:
+                      description: If the anti-affinity requirements specified 
by
+                        this field are not met at scheduling time, the pod 
will not
+                        be scheduled onto the node. If the anti-affinity 
requirements
+                        specified by this field cease to be met at some point 
during
+                        pod execution (e.g. due to a pod label update), the 
system
+                        may or may not try to eventually evict the pod from 
its node.
+                        When there are multiple elements, the lists of nodes 
corresponding
+                        to each podAffinityTerm are intersected, i.e. all 
terms must
+                        be satisfied.
+                      items:
+                        description: Defines a set of pods (namely those 
matching
+                          the labelSelector relative to the given 
namespace(s)) that
+                          this pod should be co-located (affinity) or not 
co-located
+                          (anti-affinity) with, where co-located is defined as 
running
+                          on a node whose value of the label with key 
<topologyKey>
+                          matches that of any node on which a pod of the set 
of pods
+                          is running
+                        properties:
+                          labelSelector:
+                            description: A label query over a set of 
resources, in
+                              this case pods.
+                            properties:
+                              matchExpressions:
+                                description: matchExpressions is a list of 
label selector
+                                  requirements. The requirements are ANDed.
+                                items:
+                                  description: A label selector requirement is 
a selector
+                                    that contains values, a key, and an 
operator that
+                                    relates the key and values.
+                                  properties:
+                                    key:
+                                      description: key is the label key that 
the selector
+                                        applies to.
+                                      type: string
+                                    operator:
+                                      description: operator represents a key's 
relationship
+                                        to a set of values. Valid operators 
are In,
+                                        NotIn, Exists and DoesNotExist.
+                                      type: string
+                                    values:
+                                      description: values is an array of 
string values.
+                                        If the operator is In or NotIn, the 
values
+                                        array must be non-empty. If the 
operator is
+                                        Exists or DoesNotExist, the values 
array must
+                                        be empty. This array is replaced 
during a
+                                        strategic merge patch.
+                                      items:
+                                        type: string
+                                      type: array
+                                  required:
+                                  - key
+                                  - operator
+                                  type: object
+                                type: array
+                              matchLabels:
+                                additionalProperties:
+                                  type: string
+                                description: matchLabels is a map of 
{key,value} pairs.
+                                  A single {key,value} in the matchLabels map 
is equivalent
+                                  to an element of matchExpressions, whose key 
field
+                                  is "key", the operator is "In", and the 
values array
+                                  contains only "value". The requirements are 
ANDed.
+                                type: object
+                            type: object
+                          namespaces:
+                            description: namespaces specifies which namespaces 
the
+                              labelSelector applies to (matches against); null 
or
+                              empty list means "this pod's namespace"
+                            items:
+                              type: string
+                            type: array
+                          topologyKey:
+                            description: This pod should be co-located 
(affinity)
+                              or not co-located (anti-affinity) with the pods 
matching
+                              the labelSelector in the specified namespaces, 
where
+                              co-located is defined as running on a node whose 
value
+                              of the label with key topologyKey matches that 
of any
+                              node on which any of the selected pods is 
running. Empty
+                              topologyKey is not allowed.
+                            type: string
+                        required:
+                        - topologyKey
+                        type: object
+                      type: array
+                  type: object
+              type: object
+            config:
+              additionalProperties:
+                type: string
+              description: Config holds the OAP server configuration.
+              type: object
+            image:
+              description: Image is the OAP Server Docker image to deploy.
+              type: string
+            instances:
+              description: Count is the number of OAP servers
+              type: integer
+            nodeSelector:
+              additionalProperties:
+                type: string
+              description: 'NodeSelector is a selector which must be true for 
the
+                pod to fit on a node. Selector which must match a node''s 
labels for
+                the pod to be scheduled on that node. More info: 
https://kubernetes.io/docs/concepts/configuration/assign-pod-node/'
+              type: object
+            resources:
+              description: Resources holds ResourceRequirements for the OAP 
server
+                containers
+              properties:
+                limits:
+                  additionalProperties:
+                    type: string
+                  description: 'Limits describes the maximum amount of compute 
resources
+                    allowed. More info: 
https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                  type: object
+                requests:
+                  additionalProperties:
+                    type: string
+                  description: 'Requests describes the minimum amount of 
compute resources
+                    required. If Requests is omitted for a container, it 
defaults
+                    to Limits if that is explicitly specified, otherwise to an 
implementation-defined
+                    value. More info: 
https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                  type: object
+              type: object
+            tolerations:
+              description: Tolerations allows specifying a list of tolerations 
for
+                controlling which set of Nodes a Pod can be scheduled on
+              items:
+                description: The pod this Toleration is attached to tolerates 
any
+                  taint that matches the triple <key,value,effect> using the 
matching
+                  operator <operator>.
+                properties:
+                  effect:
+                    description: Effect indicates the taint effect to match. 
Empty
+                      means match all taint effects. When specified, allowed 
values
+                      are NoSchedule, PreferNoSchedule and NoExecute.
+                    type: string
+                  key:
+                    description: Key is the taint key that the toleration 
applies
+                      to. Empty means match all taint keys. If the key is 
empty, operator
+                      must be Exists; this combination means to match all 
values and
+                      all keys.
+                    type: string
+                  operator:
+                    description: Operator represents a key's relationship to 
the value.
+                      Valid operators are Exists and Equal. Defaults to Equal. 
Exists
+                      is equivalent to wildcard for value, so that a pod can 
tolerate
+                      all taints of a particular category.
+                    type: string
+                  tolerationSeconds:
+                    description: TolerationSeconds represents the period of 
time the
+                      toleration (which must be of effect NoExecute, otherwise 
this
+                      field is ignored) tolerates the taint. By default, it is 
not
+                      set, which means tolerate the taint forever (do not 
evict).
+                      Zero and negative values will be treated as 0 (evict 
immediately)
+                      by the system.
+                    format: int64
+                    type: integer
+                  value:
+                    description: Value is the taint value the toleration 
matches to.
+                      If the operator is Exists, the value should be empty, 
otherwise
+                      just a regular string.
+                    type: string
+                type: object
+              type: array
+            version:
+              description: Version of OAP.
+              type: string
+          required:
+          - instances
+          - version
+          type: object
+        status:
+          description: OAPServerStatus defines the observed state of OAPServer
+          properties:
+            message:
+              description: A human readable message indicating details about 
why the
+                OAP servers is in this phase.
+              type: string
+            phase:
+              description: The phase OAP servers is in.
+              type: string
+            reason:
+              description: A brief CamelCase message indicating details about 
why
+                the OAP servers is in this state.
+              type: string
+          type: object
+      type: object
+  version: v1alpha1
+  versions:
+  - name: v1alpha1
+    served: true
+    storage: true
+status:
+  acceptedNames:
+    kind: ""
+    plural: ""
+  conditions: []
+  storedVersions: []
diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml
new file mode 100644
index 0000000..b391b8e
--- /dev/null
+++ b/config/crd/kustomization.yaml
@@ -0,0 +1,21 @@
+# This kustomization.yaml is not intended to be run by itself,
+# since it depends on service name and namespace that are out of this 
kustomize package.
+# It should be run by config/default
+resources:
+- bases/operator.skywalking.apache.org_oapservers.yaml
+# +kubebuilder:scaffold:crdkustomizeresource
+
+patchesStrategicMerge:
+# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] 
prefix.
+# patches here are for enabling the conversion webhook for each CRD
+#- patches/webhook_in_oapservers.yaml
+# +kubebuilder:scaffold:crdkustomizewebhookpatch
+
+# [CERTMANAGER] To enable webhook, uncomment all the sections with 
[CERTMANAGER] prefix.
+# patches here are for enabling the CA injection for each CRD
+#- patches/cainjection_in_oapservers.yaml
+# +kubebuilder:scaffold:crdkustomizecainjectionpatch
+
+# the following config is for teaching kustomize how to do kustomization for 
CRDs.
+configurations:
+- kustomizeconfig.yaml
diff --git a/config/crd/kustomizeconfig.yaml b/config/crd/kustomizeconfig.yaml
new file mode 100644
index 0000000..6f83d9a
--- /dev/null
+++ b/config/crd/kustomizeconfig.yaml
@@ -0,0 +1,17 @@
+# This file is for teaching kustomize how to substitute name and namespace 
reference in CRD
+nameReference:
+- kind: Service
+  version: v1
+  fieldSpecs:
+  - kind: CustomResourceDefinition
+    group: apiextensions.k8s.io
+    path: spec/conversion/webhookClientConfig/service/name
+
+namespace:
+- kind: CustomResourceDefinition
+  group: apiextensions.k8s.io
+  path: spec/conversion/webhookClientConfig/service/namespace
+  create: false
+
+varReference:
+- path: metadata/annotations
diff --git a/config/crd/patches/cainjection_in_oapservers.yaml 
b/config/crd/patches/cainjection_in_oapservers.yaml
new file mode 100644
index 0000000..17e24cf
--- /dev/null
+++ b/config/crd/patches/cainjection_in_oapservers.yaml
@@ -0,0 +1,8 @@
+# The following patch adds a directive for certmanager to inject CA into the 
CRD
+# CRD conversion requires k8s 1.13 or later.
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    cert-manager.io/inject-ca-from: 
$(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
+  name: oapservers.operator.skywalking.apache.org
diff --git a/config/crd/patches/webhook_in_oapservers.yaml 
b/config/crd/patches/webhook_in_oapservers.yaml
new file mode 100644
index 0000000..b1846c1
--- /dev/null
+++ b/config/crd/patches/webhook_in_oapservers.yaml
@@ -0,0 +1,17 @@
+# The following patch enables conversion webhook for CRD
+# CRD conversion requires k8s 1.13 or later.
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  name: oapservers.operator.skywalking.apache.org
+spec:
+  conversion:
+    strategy: Webhook
+    webhookClientConfig:
+      # this is "\n" used as a placeholder, otherwise it will be rejected by 
the apiserver for being blank,
+      # but we're going to set it later using the cert-manager (or potentially 
a patch if not using cert-manager)
+      caBundle: Cg==
+      service:
+        namespace: system
+        name: webhook-service
+        path: /convert
diff --git a/config/rbac/oapserver_editor_role.yaml 
b/config/rbac/oapserver_editor_role.yaml
new file mode 100644
index 0000000..5c46c84
--- /dev/null
+++ b/config/rbac/oapserver_editor_role.yaml
@@ -0,0 +1,24 @@
+# permissions for end users to edit oapservers.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: oapserver-editor-role
+rules:
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapservers
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapservers/status
+  verbs:
+  - get
diff --git a/config/rbac/oapserver_viewer_role.yaml 
b/config/rbac/oapserver_viewer_role.yaml
new file mode 100644
index 0000000..97cdbab
--- /dev/null
+++ b/config/rbac/oapserver_viewer_role.yaml
@@ -0,0 +1,20 @@
+# permissions for end users to view oapservers.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: oapserver-viewer-role
+rules:
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapservers
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapservers/status
+  verbs:
+  - get
diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml
new file mode 100644
index 0000000..8424a5f
--- /dev/null
+++ b/config/rbac/role.yaml
@@ -0,0 +1,28 @@
+
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  creationTimestamp: null
+  name: manager-role
+rules:
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapservers
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - operator.skywalking.apache.org
+  resources:
+  - oapservers/status
+  verbs:
+  - get
+  - patch
+  - update
diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml
new file mode 100644
index 0000000..e69de29
diff --git a/controllers/oapserver_controller.go 
b/controllers/oapserver_controller.go
new file mode 100644
index 0000000..fd107bc
--- /dev/null
+++ b/controllers/oapserver_controller.go
@@ -0,0 +1,54 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package controllers
+
+import (
+       "context"
+
+       "github.com/go-logr/logr"
+       "k8s.io/apimachinery/pkg/runtime"
+       ctrl "sigs.k8s.io/controller-runtime"
+       "sigs.k8s.io/controller-runtime/pkg/client"
+
+       operatorv1alpha1 "github.com/skywalking-swck/api/v1alpha1"
+)
+
+// OAPServerReconciler reconciles a OAPServer object
+type OAPServerReconciler struct {
+       client.Client
+       Log    logr.Logger
+       Scheme *runtime.Scheme
+}
+
+// 
+kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=oapservers,verbs=get;list;watch;create;update;patch;delete
+// 
+kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=oapservers/status,verbs=get;update;patch
+
+func (r *OAPServerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) 
{
+       _ = context.Background()
+       _ = r.Log.WithValues("oapserver", req.NamespacedName)
+
+       // your logic here
+
+       return ctrl.Result{}, nil
+}
+
+func (r *OAPServerReconciler) SetupWithManager(mgr ctrl.Manager) error {
+       return ctrl.NewControllerManagedBy(mgr).
+               For(&operatorv1alpha1.OAPServer{}).
+               Complete(r)
+}
diff --git a/controllers/suite_test.go b/controllers/suite_test.go
new file mode 100644
index 0000000..da4c6d1
--- /dev/null
+++ b/controllers/suite_test.go
@@ -0,0 +1,81 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package controllers
+
+import (
+       "path/filepath"
+       "testing"
+
+       . "github.com/onsi/ginkgo"
+       . "github.com/onsi/gomega"
+       "k8s.io/client-go/kubernetes/scheme"
+       "k8s.io/client-go/rest"
+       "sigs.k8s.io/controller-runtime/pkg/client"
+       "sigs.k8s.io/controller-runtime/pkg/envtest"
+       logf "sigs.k8s.io/controller-runtime/pkg/log"
+       "sigs.k8s.io/controller-runtime/pkg/log/zap"
+
+       operatorv1alpha1 "github.com/skywalking-swck/api/v1alpha1"
+       // +kubebuilder:scaffold:imports
+)
+
+// These tests use Ginkgo (BDD-style Go testing framework). Refer to
+// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
+
+var cfg *rest.Config
+var k8sClient client.Client
+var testEnv *envtest.Environment
+
+func TestAPIs(t *testing.T) {
+       RegisterFailHandler(Fail)
+
+       RunSpecsWithDefaultAndCustomReporters(t,
+               "Controller Suite",
+               []Reporter{envtest.NewlineReporter{}})
+}
+
+var _ = BeforeSuite(func(done Done) {
+       logf.SetLogger(zap.LoggerTo(GinkgoWriter, true))
+
+       By("bootstrapping test environment")
+       testEnv = &envtest.Environment{
+               CRDDirectoryPaths: []string{filepath.Join("..", "config", 
"crd", "bases")},
+       }
+
+       var err error
+       cfg, err = testEnv.Start()
+       Expect(err).ToNot(HaveOccurred())
+       Expect(cfg).ToNot(BeNil())
+
+       err = operatorv1alpha1.AddToScheme(scheme.Scheme)
+       Expect(err).NotTo(HaveOccurred())
+
+       // +kubebuilder:scaffold:scheme
+
+       k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
+       Expect(err).ToNot(HaveOccurred())
+       Expect(k8sClient).ToNot(BeNil())
+
+       close(done)
+}, 60)
+
+var _ = AfterSuite(func() {
+       By("tearing down the test environment")
+       err := testEnv.Stop()
+       Expect(err).ToNot(HaveOccurred())
+})
diff --git a/go.mod b/go.mod
index f37ced2..6082d91 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,10 @@ module github.com/skywalking-swck
 go 1.13
 
 require (
+       github.com/go-logr/logr v0.1.0
+       github.com/onsi/ginkgo v1.8.0
+       github.com/onsi/gomega v1.5.0
+       k8s.io/api v0.0.0-20190918155943-95b840bb6a1f
        k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655
        k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90
        sigs.k8s.io/controller-runtime v0.4.0
diff --git a/main.go b/main.go
index f4851c7..0cfcf25 100644
--- a/main.go
+++ b/main.go
@@ -26,6 +26,9 @@ import (
        _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
        ctrl "sigs.k8s.io/controller-runtime"
        "sigs.k8s.io/controller-runtime/pkg/log/zap"
+
+       operatorv1alpha1 "github.com/skywalking-swck/api/v1alpha1"
+       "github.com/skywalking-swck/controllers"
        // +kubebuilder:scaffold:imports
 )
 
@@ -37,6 +40,7 @@ var (
 func init() {
        _ = clientgoscheme.AddToScheme(scheme)
 
+       _ = operatorv1alpha1.AddToScheme(scheme)
        // +kubebuilder:scaffold:scheme
 }
 
@@ -64,6 +68,14 @@ func main() {
                os.Exit(1)
        }
 
+       if err = (&controllers.OAPServerReconciler{
+               Client: mgr.GetClient(),
+               Log:    ctrl.Log.WithName("controllers").WithName("OAPServer"),
+               Scheme: mgr.GetScheme(),
+       }).SetupWithManager(mgr); err != nil {
+               setupLog.Error(err, "unable to create controller", 
"controller", "OAPServer")
+               os.Exit(1)
+       }
        // +kubebuilder:scaffold:builder
 
        setupLog.Info("starting manager")

Reply via email to