This commit is contained in:
Chris Lu 2020-08-01 23:27:46 -07:00
parent f65a532f78
commit 9b075d68ce
31 changed files with 405 additions and 561 deletions

View File

@ -11,8 +11,6 @@ BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)
endif
BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)
.PHONY: bundle
# Image URL to use all building/pushing image targets
IMG ?= controller:latest
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
@ -111,7 +109,7 @@ endif
# Generate bundle manifests and metadata, then validate generated files.
bundle: manifests
operator-sdk generate kustomize manifests -q
$(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)
kustomize build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)
operator-sdk bundle validate ./bundle
# Build the bundle image.

View File

@ -1,11 +1,10 @@
domain: seaweedfs.com
layout: go.kubebuilder.io/v2
multigroup: true
repo: github.com/seaweedfs/seaweedfs-operator
resources:
- group: objectstore
kind: Master
version: v100
- group: seaweed
kind: Seaweed
version: v1
version: 3-alpha
plugins:
go.sdk.operatorframework.io/v2-alpha: {}
go.operator-sdk.io/v2-alpha: {}

View File

@ -17,6 +17,6 @@ $ make install
$ make run ENABLE_WEBHOOKS=false
# From another terminal in the same directory
$ kubectl apply -f config/samples/objectstore_v100_master.yaml
$ kubectl apply -f config/samples/seaweed_v1_seaweed.yaml
```

View File

@ -1,5 +1,5 @@
/*
Copyright 2020 SeaweedFS.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,10 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package v100 contains API Schema definitions for the objectstore v100 API group
// Package v1 contains API Schema definitions for the seaweed v1 API group
// +kubebuilder:object:generate=true
// +groupName=objectstore.seaweedfs.com
package v100
// +groupName=seaweed.seaweedfs.com
package v1
import (
"k8s.io/apimachinery/pkg/runtime/schema"
@ -26,7 +26,7 @@ import (
var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "objectstore.seaweedfs.com", Version: "v100"}
GroupVersion = schema.GroupVersion{Group: "seaweed.seaweedfs.com", Version: "v1"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}

View File

@ -1,5 +1,5 @@
/*
Copyright 2020 SeaweedFS.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v100
package v1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -23,19 +23,17 @@ import (
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// MasterSpec defines the desired state of Master
type MasterSpec struct {
// SeaweedSpec defines the desired state of Seaweed
type SeaweedSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Mdir is the directory to store meta data
Mdir string `json:"mdir,omitempty"`
// MetricsAddress is Prometheus gateway address
MetricsAddress string `json:"metricsAddress,omitempty"`
}
// MasterStatus defines the observed state of Master
type MasterStatus struct {
// SeaweedStatus defines the observed state of Seaweed
type SeaweedStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}
@ -43,24 +41,24 @@ type MasterStatus struct {
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// Master is the Schema for the masters API
type Master struct {
// Seaweed is the Schema for the seaweeds API
type Seaweed struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec MasterSpec `json:"spec,omitempty"`
Status MasterStatus `json:"status,omitempty"`
Spec SeaweedSpec `json:"spec,omitempty"`
Status SeaweedStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// MasterList contains a list of Master
type MasterList struct {
// SeaweedList contains a list of Seaweed
type SeaweedList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Master `json:"items"`
Items []Seaweed `json:"items"`
}
func init() {
SchemeBuilder.Register(&Master{}, &MasterList{})
SchemeBuilder.Register(&Seaweed{}, &SeaweedList{})
}

View File

@ -1,7 +1,7 @@
// +build !ignore_autogenerated
/*
Copyright 2020 SeaweedFS.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -18,14 +18,14 @@ limitations under the License.
// Code generated by controller-gen. DO NOT EDIT.
package v100
package v1
import (
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 *Master) DeepCopyInto(out *Master) {
func (in *Seaweed) DeepCopyInto(out *Seaweed) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
@ -33,18 +33,18 @@ func (in *Master) DeepCopyInto(out *Master) {
out.Status = in.Status
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Master.
func (in *Master) DeepCopy() *Master {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Seaweed.
func (in *Seaweed) DeepCopy() *Seaweed {
if in == nil {
return nil
}
out := new(Master)
out := new(Seaweed)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Master) DeepCopyObject() runtime.Object {
func (in *Seaweed) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
@ -52,31 +52,31 @@ func (in *Master) DeepCopyObject() runtime.Object {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MasterList) DeepCopyInto(out *MasterList) {
func (in *SeaweedList) DeepCopyInto(out *SeaweedList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Master, len(*in))
*out = make([]Seaweed, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterList.
func (in *MasterList) DeepCopy() *MasterList {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SeaweedList.
func (in *SeaweedList) DeepCopy() *SeaweedList {
if in == nil {
return nil
}
out := new(MasterList)
out := new(SeaweedList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *MasterList) DeepCopyObject() runtime.Object {
func (in *SeaweedList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
@ -84,31 +84,31 @@ func (in *MasterList) DeepCopyObject() runtime.Object {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MasterSpec) DeepCopyInto(out *MasterSpec) {
func (in *SeaweedSpec) DeepCopyInto(out *SeaweedSpec) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterSpec.
func (in *MasterSpec) DeepCopy() *MasterSpec {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SeaweedSpec.
func (in *SeaweedSpec) DeepCopy() *SeaweedSpec {
if in == nil {
return nil
}
out := new(MasterSpec)
out := new(SeaweedSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MasterStatus) DeepCopyInto(out *MasterStatus) {
func (in *SeaweedStatus) DeepCopyInto(out *SeaweedStatus) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterStatus.
func (in *MasterStatus) DeepCopy() *MasterStatus {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SeaweedStatus.
func (in *SeaweedStatus) DeepCopy() *SeaweedStatus {
if in == nil {
return nil
}
out := new(MasterStatus)
out := new(SeaweedStatus)
in.DeepCopyInto(out)
return out
}

View File

@ -6,20 +6,20 @@ metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.3.0
creationTimestamp: null
name: masters.objectstore.seaweedfs.com
name: seaweeds.seaweed.seaweedfs.com
spec:
group: objectstore.seaweedfs.com
group: seaweed.seaweedfs.com
names:
kind: Master
listKind: MasterList
plural: masters
singular: master
kind: Seaweed
listKind: SeaweedList
plural: seaweeds
singular: seaweed
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: Master is the Schema for the masters API
description: Seaweed is the Schema for the seaweeds API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
@ -34,22 +34,19 @@ spec:
metadata:
type: object
spec:
description: MasterSpec defines the desired state of Master
description: SeaweedSpec defines the desired state of Seaweed
properties:
mdir:
description: Mdir is the directory to store meta data
type: string
metricsAddress:
description: MetricsAddress is Prometheus gateway address
type: string
type: object
status:
description: MasterStatus defines the observed state of Master
description: SeaweedStatus defines the observed state of Seaweed
type: object
type: object
version: v100
version: v1
versions:
- name: v100
- name: v1
served: true
storage: true
status:

View File

@ -2,18 +2,18 @@
# since it depends on service name and namespace that are out of this kustomize package.
# It should be run by config/default
resources:
- bases/objectstore.seaweedfs.com_masters.yaml
- bases/seaweed.seaweedfs.com_seaweeds.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_masters.yaml
#- patches/webhook_in_seaweeds.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_masters.yaml
#- patches/cainjection_in_seaweeds.yaml
# +kubebuilder:scaffold:crdkustomizecainjectionpatch
# the following config is for teaching kustomize how to do kustomization for CRDs.

View File

@ -5,4 +5,4 @@ kind: CustomResourceDefinition
metadata:
annotations:
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
name: masters.objectstore.seaweedfs.com
name: seaweeds.seaweed.seaweedfs.com

View File

@ -3,7 +3,7 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: masters.objectstore.seaweedfs.com
name: seaweeds.seaweed.seaweedfs.com
spec:
conversion:
strategy: Webhook

View File

@ -7,9 +7,9 @@ metadata:
name: manager-role
rules:
- apiGroups:
- objectstore.seaweedfs.com
- seaweed.seaweedfs.com
resources:
- masters
- seaweeds
verbs:
- create
- delete
@ -19,9 +19,9 @@ rules:
- update
- watch
- apiGroups:
- objectstore.seaweedfs.com
- seaweed.seaweedfs.com
resources:
- masters/status
- seaweeds/status
verbs:
- get
- patch

View File

@ -1,13 +1,13 @@
# permissions for end users to edit masters.
# permissions for end users to edit seaweeds.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: master-editor-role
name: seaweed-editor-role
rules:
- apiGroups:
- objectstore.seaweedfs.com
- seaweed.seaweedfs.com
resources:
- masters
- seaweeds
verbs:
- create
- delete
@ -17,8 +17,8 @@ rules:
- update
- watch
- apiGroups:
- objectstore.seaweedfs.com
- seaweed.seaweedfs.com
resources:
- masters/status
- seaweeds/status
verbs:
- get

View File

@ -1,20 +1,20 @@
# permissions for end users to view masters.
# permissions for end users to view seaweeds.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: master-viewer-role
name: seaweed-viewer-role
rules:
- apiGroups:
- objectstore.seaweedfs.com
- seaweed.seaweedfs.com
resources:
- masters
- seaweeds
verbs:
- get
- list
- watch
- apiGroups:
- objectstore.seaweedfs.com
- seaweed.seaweedfs.com
resources:
- masters/status
- seaweeds/status
verbs:
- get

View File

@ -1,3 +1,3 @@
## This file is auto-generated, do not modify ##
resources:
- objectstore_v100_master.yaml
- seaweed_v1_seaweed.yaml

View File

@ -1,7 +0,0 @@
apiVersion: objectstore.seaweedfs.com/v100
kind: Master
metadata:
name: master-sample
spec:
# Add fields here
foo: bar

View File

@ -0,0 +1,7 @@
apiVersion: seaweed.seaweedfs.com/v1
kind: Seaweed
metadata:
name: seaweed-sample
spec:
# Add fields here
foo: bar

View File

@ -1,7 +0,0 @@
apiVersion: scorecard.operatorframework.io/v1alpha3
kind: Configuration
metadata:
name: config
stages:
- parallel: true
tests: []

View File

@ -1,16 +0,0 @@
resources:
- bases/config.yaml
patchesJson6902:
- path: patches/basic.config.yaml
target:
group: scorecard.operatorframework.io
version: v1alpha3
kind: Configuration
name: config
- path: patches/olm.config.yaml
target:
group: scorecard.operatorframework.io
version: v1alpha3
kind: Configuration
name: config
# +kubebuilder:scaffold:patchesJson6902

View File

@ -1,10 +0,0 @@
- op: add
path: /stages/0/tests/-
value:
entrypoint:
- scorecard-test
- basic-check-spec
image: quay.io/operator-framework/scorecard-test:master
labels:
suite: basic
test: basic-check-spec-test

View File

@ -1,50 +0,0 @@
- op: add
path: /stages/0/tests/-
value:
entrypoint:
- scorecard-test
- olm-bundle-validation
image: quay.io/operator-framework/scorecard-test:master
labels:
suite: olm
test: olm-bundle-validation-test
- op: add
path: /stages/0/tests/-
value:
entrypoint:
- scorecard-test
- olm-crds-have-validation
image: quay.io/operator-framework/scorecard-test:master
labels:
suite: olm
test: olm-crds-have-validation-test
- op: add
path: /stages/0/tests/-
value:
entrypoint:
- scorecard-test
- olm-crds-have-resources
image: quay.io/operator-framework/scorecard-test:master
labels:
suite: olm
test: olm-crds-have-resources-test
- op: add
path: /stages/0/tests/-
value:
entrypoint:
- scorecard-test
- olm-spec-descriptors
image: quay.io/operator-framework/scorecard-test:master
labels:
suite: olm
test: olm-spec-descriptors-test
- op: add
path: /stages/0/tests/-
value:
entrypoint:
- scorecard-test
- olm-status-descriptors
image: quay.io/operator-framework/scorecard-test:master
labels:
suite: olm
test: olm-status-descriptors-test

View File

@ -0,0 +1,89 @@
package controllers
import (
"context"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
seaweedv1 "github.com/seaweedfs/seaweedfs-operator/api/v1"
)
const (
MasterClusterSize = 3
)
func (r *SeaweedReconciler) ensureMaster(seaweedCR *seaweedv1.Seaweed) (done bool, result ctrl.Result, err error) {
_ = context.Background()
_ = r.Log.WithValues("seaweed", seaweedCR.Name)
if done, result, err = r.ensureMasterStatefulSet(seaweedCR); done {
return done, result, err
}
for masterIndex := 0; masterIndex < MasterClusterSize; masterIndex++ {
if done, result, err = r.ensureMasterService(seaweedCR, masterIndex); done {
return done, result, err
}
}
return false, ctrl.Result{}, nil
}
func (r *SeaweedReconciler) ensureMasterStatefulSet(seaweedCR *seaweedv1.Seaweed) (bool, ctrl.Result, error) {
ctx := context.Background()
log := r.Log.WithValues("sw-master-statefulset", seaweedCR.Name)
masterStatefulSet := &appsv1.StatefulSet{}
err := r.Get(ctx, types.NamespacedName{Name: seaweedCR.Name, Namespace: seaweedCR.Namespace}, masterStatefulSet)
if err != nil && errors.IsNotFound(err) {
// Define a new deployment
dep := r.createMasterStatefulSet(seaweedCR)
log.Info("Creating a new master statefulset", "Namespace", dep.Namespace, "Name", dep.Name)
err = r.Create(ctx, dep)
if err != nil {
log.Error(err, "Failed to create new statefulset", "Namespace", dep.Namespace, "Name", dep.Name)
return true, ctrl.Result{}, err
}
// Deployment created successfully - return and requeue
return true, ctrl.Result{Requeue: true}, nil
} else if err != nil {
log.Error(err, "Failed to get Deployment")
return true, ctrl.Result{}, err
}
log.Info("Get master cluster " + masterStatefulSet.Name)
return false, ctrl.Result{}, nil
}
func (r *SeaweedReconciler) ensureMasterService(seaweedCR *seaweedv1.Seaweed, masterIndex int) (bool, ctrl.Result, error) {
ctx := context.Background()
log := r.Log.WithValues("sw-master-service", seaweedCR.Name)
masterService := &corev1.Service{}
err := r.Get(ctx, types.NamespacedName{Name: seaweedCR.Name, Namespace: seaweedCR.Namespace}, masterService)
if err != nil && errors.IsNotFound(err) {
// Define a new deployment
dep := r.createMasterService(seaweedCR, masterIndex)
log.Info("Creating a new master headless service", "Namespace", dep.Namespace, "Name", dep.Name)
err = r.Create(ctx, dep)
if err != nil {
log.Error(err, "Failed to creater service master", "masterIndex", masterIndex)
return true, ctrl.Result{}, err
}
// Deployment created successfully - return and requeue
return true, ctrl.Result{Requeue: true}, nil
} else if err != nil {
log.Error(err, "Failed to get service master", "masterIndex", masterIndex)
return true, ctrl.Result{}, err
}
log.Info("Get master service " + masterService.Name)
return false, ctrl.Result{}, nil
}
func labelsForMaster(name string) map[string]string {
return map[string]string{"app": "seaweedfs", "role": "master", "name": name}
}

View File

@ -0,0 +1,50 @@
package controllers
import (
"fmt"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
seaweedv1 "github.com/seaweedfs/seaweedfs-operator/api/v1"
)
func (r *SeaweedReconciler) createMasterService(m *seaweedv1.Seaweed, masterIndex int) *corev1.Service {
labels := labelsForMaster(m.Name)
labels["name"] = fmt.Sprintf("master-%d", masterIndex)
dep := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: m.Name,
Namespace: m.Namespace,
},
Spec: corev1.ServiceSpec{
ClusterIP: "None",
Ports: []corev1.ServicePort{
{
Name: "swfs-master",
Protocol: corev1.Protocol("TCP"),
Port: 9333,
TargetPort: intstr.IntOrString{
Type: intstr.Int,
IntVal: 9333,
},
},
{
Name: "swfs-master-grpc",
Protocol: corev1.Protocol("TCP"),
Port: 19333,
TargetPort: intstr.IntOrString{
Type: intstr.Int,
IntVal: 19333,
},
},
},
Selector: labels,
},
}
// Set master instance as the owner and controller
// ctrl.SetControllerReference(m, dep, r.Scheme)
return dep
}

View File

@ -0,0 +1,85 @@
package controllers
import (
"fmt"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
seaweedv1 "github.com/seaweedfs/seaweedfs-operator/api/v1"
)
func (r *SeaweedReconciler) createMasterStatefulSet(m *seaweedv1.Seaweed) *appsv1.StatefulSet {
labels := labelsForMaster(m.Name)
replicas := int32(MasterClusterSize)
dep := &appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: m.Name,
Namespace: m.Namespace,
},
Spec: appsv1.StatefulSetSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: labels,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: labels,
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Image: "chrislusf/seaweedfs:latest",
Name: "master",
Env: []corev1.EnvVar{
{
Name: "POD_IP",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "status.podIP",
},
},
},
{
Name: "POD_NAME",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
},
},
},
{
Name: "NAMESPACE",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.namespace",
},
},
},
},
Command: []string{
"weed",
"master",
"-volumeSizeLimitMB=1000",
"-ip=$(POD_NAME)",
fmt.Sprintf("-peers=%s-0:9333,%s-1:9333,%s-2:9333", m.Name, m.Name, m.Name),
},
Ports: []corev1.ContainerPort{
{
ContainerPort: 9333,
Name: "swfs-master",
},
{
ContainerPort: 19333,
},
},
}},
},
},
},
}
// Set master instance as the owner and controller
// ctrl.SetControllerReference(m, dep, r.Scheme)
return dep
}

View File

@ -1,143 +0,0 @@
/*
Copyright 2020 SeaweedFS.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controllers
import (
"context"
"time"
"github.com/go-logr/logr"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
objectstorev100 "github.com/seaweedfs/seaweedfs-operator/apis/objectstore/v100"
)
// MasterReconciler reconciles a Master object
type MasterReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
}
// +kubebuilder:rbac:groups=objectstore.seaweedfs.com,resources=masters,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=objectstore.seaweedfs.com,resources=masters/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;
func (r *MasterReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
ctx := context.Background()
log := r.Log.WithValues("master", req.NamespacedName)
// your logic here
log.Info("start Reconcile ...")
master, done, result, err := r.findMasterCustomResourceInstance(ctx, log, req)
if done {
return result, err
}
if done, result, err = r.ensureMasterStatefulSet(ctx, log, master); done {
return result, err
}
if done, result, err = r.ensureMasterService(ctx, log, master); done {
return result, err
}
// Update the Memcached status with the pod names
// List the pods for this memcached's deployment
podList := &corev1.PodList{}
listOpts := []client.ListOption{
client.InNamespace(master.Namespace),
client.MatchingLabels(lablesForMaster(master.Name)),
}
if err = r.List(ctx, podList, listOpts...); err != nil {
log.Error(err, "Failed to list pods", "Memcached.Namespace", master.Namespace, "Memcached.Name", master.Name)
return ctrl.Result{}, err
}
log.Info("pods", "count", len(podList.Items))
for _, pod := range podList.Items {
log.Info("pod", "name", pod.Name, "podIP", pod.Status.PodIP)
}
return ctrl.Result{RequeueAfter: time.Second * 5}, nil
}
// deploymentForMaster returns a memcached Deployment object
func (r *MasterReconciler) deploymentForMaster(m *objectstorev100.Master) *appsv1.Deployment {
ls := lablesForMaster(m.Name)
replicas := int32(0)
dep := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: m.Name,
Namespace: m.Namespace,
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: ls,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: ls,
},
Spec: corev1.PodSpec{
Hostname: "mastername",
Containers: []corev1.Container{{
Image: "chrislusf/seaweedfs:latest",
Name: "master",
Command: []string{"weed", "master"},
Ports: []corev1.ContainerPort{{
ContainerPort: 9333,
Name: "master",
}},
}},
},
},
},
}
// Set Memcached instance as the owner and controller
ctrl.SetControllerReference(m, dep, r.Scheme)
return dep
}
// lablesForMaster returns the labels for selecting the resources
// belonging to the given memcached CR name.
func lablesForMaster(name string) map[string]string {
return map[string]string{"app": "seaweedfs", "role": "master", "name": name}
}
// getPodNames returns the pod names of the array of pods passed in
func getPodNames(pods []corev1.Pod) []string {
var podNames []string
for _, pod := range pods {
podNames = append(podNames, pod.Name)
}
return podNames
}
func (r *MasterReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&objectstorev100.Master{}).
Complete(r)
}

View File

@ -1,197 +0,0 @@
package controllers
import (
"context"
"time"
"github.com/go-logr/logr"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
ctrl "sigs.k8s.io/controller-runtime"
objectstorev100 "github.com/seaweedfs/seaweedfs-operator/apis/objectstore/v100"
)
func (r *MasterReconciler) findMasterCustomResourceInstance(ctx context.Context, log logr.Logger, req ctrl.Request) (*objectstorev100.Master, bool, ctrl.Result, error) {
// fetch the master instance
master := &objectstorev100.Master{}
err := r.Get(ctx, req.NamespacedName, master)
if err != nil {
if errors.IsNotFound(err) {
// Request object not found, could have been deleted after reconcile request.
// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
// Return and don't requeue
log.Info("Master resource not found. Ignoring since object must be deleted")
return nil, true, ctrl.Result{RequeueAfter: time.Second * 5}, nil
}
// Error reading the object - requeue the request.
log.Error(err, "Failed to get Master")
return nil, true, ctrl.Result{}, err
}
log.Info("Get master " + master.Name)
return master, false, ctrl.Result{}, nil
}
func (r *MasterReconciler) ensureMasterStatefulSet(ctx context.Context, log logr.Logger, master *objectstorev100.Master) (bool, ctrl.Result, error) {
// fetch the master instance
masterCluster := &appsv1.StatefulSet{}
err := r.Get(ctx, types.NamespacedName{Name: master.Name, Namespace: master.Namespace}, masterCluster)
if err != nil && errors.IsNotFound(err) {
// Define a new deployment
dep := r.createMasterStatefulSet(master)
log.Info("Creating a new master cluster statefulset", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
err = r.Create(ctx, dep)
if err != nil {
log.Error(err, "Failed to create new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
return true, ctrl.Result{}, err
}
// Deployment created successfully - return and requeue
return true, ctrl.Result{Requeue: true}, nil
} else if err != nil {
log.Error(err, "Failed to get Deployment")
return true, ctrl.Result{}, err
}
log.Info("Get master cluster " + masterCluster.Name)
return false, ctrl.Result{}, nil
}
// deploymentForMaster returns a memcached Deployment object
func (r *MasterReconciler) createMasterStatefulSet(m *objectstorev100.Master) *appsv1.StatefulSet {
labels := lablesForMaster(m.Name)
replicas := int32(3)
enableServiceLinks := false
dep := &appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: m.Name,
Namespace: m.Namespace,
},
Spec: appsv1.StatefulSetSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: labels,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: labels,
},
Spec: corev1.PodSpec{
Volumes: nil,
InitContainers: nil,
Containers: []corev1.Container{{
Image: "chrislusf/seaweedfs:latest",
Name: "master",
Env: []corev1.EnvVar{
{
Name: "POD_IP",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "status.podIP",
},
},
},
{
Name: "POD_NAME",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
},
},
},
{
Name: "NAMESPACE",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.namespace",
},
},
},
},
Command: []string{"weed", "master", "-volumeSizeLimitMB=1000", "-ip=${POD_NAME}"},
Ports: []corev1.ContainerPort{
{
ContainerPort: 9333,
Name: "swfs-master",
},
{
ContainerPort: 19333,
},
},
}},
EnableServiceLinks: &enableServiceLinks,
},
},
},
}
// Set master instance as the owner and controller
// ctrl.SetControllerReference(m, dep, r.Scheme)
return dep
}
func (r *MasterReconciler) ensureMasterService(ctx context.Context, log logr.Logger, master *objectstorev100.Master) (bool, ctrl.Result, error) {
// fetch the master instance
masterService := &corev1.Service{}
err := r.Get(ctx, types.NamespacedName{Name: master.Name, Namespace: master.Namespace}, masterService)
if err != nil && errors.IsNotFound(err) {
// Define a new deployment
dep := r.createMasterService(master)
log.Info("Creating a new master cluster statefulset", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
err = r.Create(ctx, dep)
if err != nil {
log.Error(err, "Failed to create new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
return true, ctrl.Result{}, err
}
// Deployment created successfully - return and requeue
return true, ctrl.Result{Requeue: true}, nil
} else if err != nil {
log.Error(err, "Failed to get Deployment")
return true, ctrl.Result{}, err
}
log.Info("Get master cluster " + masterService.Name)
return false, ctrl.Result{}, nil
}
// deploymentForMaster returns a memcached Deployment object
func (r *MasterReconciler) createMasterService(m *objectstorev100.Master) *corev1.Service {
labels := lablesForMaster(m.Name)
dep := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: m.Name,
Namespace: m.Namespace,
},
Spec: corev1.ServiceSpec{
ClusterIP: "None",
Ports: []corev1.ServicePort{
{
Name: "swfs-master",
Protocol: corev1.Protocol("TCP"),
Port: 9333,
TargetPort: intstr.IntOrString{
Type: intstr.Int,
IntVal: 9333,
},
},
{
Name: "swfs-master-grpc",
Protocol: corev1.Protocol("TCP"),
Port: 19333,
TargetPort: intstr.IntOrString{
Type: intstr.Int,
IntVal: 19333,
},
},
},
Selector: labels,
},
}
// Set master instance as the owner and controller
// ctrl.SetControllerReference(m, dep, r.Scheme)
return dep
}

View File

@ -0,0 +1,84 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controllers
import (
"context"
"time"
"github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
seaweedv1 "github.com/seaweedfs/seaweedfs-operator/api/v1"
)
// SeaweedReconciler reconciles a Seaweed object
type SeaweedReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
}
// +kubebuilder:rbac:groups=seaweed.seaweedfs.com,resources=seaweeds,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=seaweed.seaweedfs.com,resources=seaweeds/status,verbs=get;update;patch
func (r *SeaweedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
ctx := context.Background()
log := r.Log.WithValues("seaweed", req.NamespacedName)
seaweedCR, done, result, err := r.findSeaweedCustomResourceInstance(ctx, log, req)
if done {
return result, err
}
if done, result, err = r.ensureMaster(seaweedCR); done {
return result, err
}
log.Info("start Reconcile ...")
return ctrl.Result{}, nil
}
func (r *SeaweedReconciler) findSeaweedCustomResourceInstance(ctx context.Context, log logr.Logger, req ctrl.Request) (*seaweedv1.Seaweed, bool, ctrl.Result, error) {
// fetch the master instance
seaweedCR := &seaweedv1.Seaweed{}
err := r.Get(ctx, req.NamespacedName, seaweedCR)
if err != nil {
if errors.IsNotFound(err) {
// Request object not found, could have been deleted after reconcile request.
// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
// Return and don't requeue
log.Info("Seaweed CR not found. Ignoring since object must be deleted")
return nil, true, ctrl.Result{RequeueAfter: time.Second * 5}, nil
}
// Error reading the object - requeue the request.
log.Error(err, "Failed to get SeaweedCR")
return nil, true, ctrl.Result{}, err
}
log.Info("Get master " + seaweedCR.Name)
return seaweedCR, false, ctrl.Result{}, nil
}
func (r *SeaweedReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&seaweedv1.Seaweed{}).
Complete(r)
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2020 SeaweedFS.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -30,7 +30,7 @@ import (
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
objectstorev100 "github.com/seaweedfs/seaweedfs-operator/apis/objectstore/v100"
seaweedv1 "github.com/seaweedfs/seaweedfs-operator/api/v1"
// +kubebuilder:scaffold:imports
)
@ -62,7 +62,7 @@ var _ = BeforeSuite(func(done Done) {
Expect(err).ToNot(HaveOccurred())
Expect(cfg).ToNot(BeNil())
err = objectstorev100.AddToScheme(scheme.Scheme)
err = seaweedv1.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())
// +kubebuilder:scaffold:scheme

1
go.mod
View File

@ -3,7 +3,6 @@ module github.com/seaweedfs/seaweedfs-operator
go 1.13
require (
github.com/go-delve/delve v1.4.1 // indirect
github.com/go-logr/logr v0.1.0
github.com/onsi/ginkgo v1.11.0
github.com/onsi/gomega v1.8.1

32
go.sum
View File

@ -41,12 +41,8 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cosiner/argv v0.0.0-20170225145430-13bacc38a0a5 h1:rIXlvz2IWiupMFlC45cZCXZFvKX/ExBcSLrDy2G0Lp8=
github.com/cosiner/argv v0.0.0-20170225145430-13bacc38a0a5/go.mod h1:p/NrK5tF6ICIly4qwEDsf6VDirFiWWz0FenfYBwJaKQ=
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -73,8 +69,6 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-delve/delve v1.4.1 h1:kZs0umEv+VKnK84kY9/ZXWrakdLTeRTyYjFdgLelZCQ=
github.com/go-delve/delve v1.4.1/go.mod h1:vmy6iObn7zg8FQ5KOCIe6TruMNsqpoZO8uMiRea+97k=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg=
@ -145,8 +139,6 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-dap v0.2.0 h1:whjIGQRumwbR40qRU7CEKuFLmePUUc2s4Nt9DoXXxWk=
github.com/google/go-dap v0.2.0/go.mod h1:5q8aYQFnHOAZEMP+6vmq25HKYAEwE+LF5yh7JKrrhSQ=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -170,15 +162,12 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@ -191,8 +180,6 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@ -207,11 +194,7 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
@ -240,8 +223,6 @@ github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b h1:8uaXtUkxiy+T/zdLWuxa/PG4so0TPZDZfafFNNSaptE=
github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -262,24 +243,18 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.0-20170417170307-b6cb39589372/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v0.0.0-20170417173400-9e4c21054fa1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@ -305,8 +280,6 @@ go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qL
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.starlark.net v0.0.0-20190702223751-32f345186213 h1:lkYv5AKwvvduv5XWP6szk/bvvgO6aDeUujhZQXIFTes=
go.starlark.net v0.0.0-20190702223751-32f345186213/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@ -314,8 +287,6 @@ go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4 h1:QlVATYS7JBoZMVaf+cNjb90WD/beKVHnIxFKT4QaHVI=
golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@ -371,7 +342,6 @@ golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -397,7 +367,6 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0=
@ -461,7 +430,6 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c h1:/KUFqjjqAcY4Us6luF5RDN
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
sigs.k8s.io/controller-runtime v0.6.0 h1:Fzna3DY7c4BIP6KwfSlrfnj20DJ+SeMBK8HSFvOk9NM=
sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo=

View File

@ -1,5 +1,5 @@
/*
Copyright 2020 SeaweedFS.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

14
main.go
View File

@ -1,5 +1,5 @@
/*
Copyright 2020 SeaweedFS.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -27,8 +27,8 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
objectstorev100 "github.com/seaweedfs/seaweedfs-operator/apis/objectstore/v100"
objectstorecontroller "github.com/seaweedfs/seaweedfs-operator/controllers/objectstore"
seaweedv1 "github.com/seaweedfs/seaweedfs-operator/api/v1"
"github.com/seaweedfs/seaweedfs-operator/controllers"
// +kubebuilder:scaffold:imports
)
@ -40,7 +40,7 @@ var (
func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(objectstorev100.AddToScheme(scheme))
utilruntime.Must(seaweedv1.AddToScheme(scheme))
// +kubebuilder:scaffold:scheme
}
@ -67,12 +67,12 @@ func main() {
os.Exit(1)
}
if err = (&objectstorecontroller.MasterReconciler{
if err = (&controllers.SeaweedReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("Master"),
Log: ctrl.Log.WithName("controllers").WithName("Seaweed"),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Master")
setupLog.Error(err, "unable to create controller", "controller", "Seaweed")
os.Exit(1)
}
// +kubebuilder:scaffold:builder