-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Mengqi Yu
committed
Feb 22, 2019
1 parent
5f14019
commit 5264408
Showing
8 changed files
with
496 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Build the manager binary | ||
FROM golang:1.11.5 as builder | ||
|
||
# Copy in the go src | ||
WORKDIR /go/src/sigs.k8s.io/controller-runtime/ | ||
COPY pkg/ pkg/ | ||
COPY crdexample/ crdexample/ | ||
COPY vendor/ vendor/ | ||
|
||
# Build | ||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager ./crdexample | ||
|
||
# Copy the controller-manager into a thin image | ||
FROM ubuntu:latest | ||
WORKDIR / | ||
COPY --from=builder /go/src/sigs.k8s.io/controller-runtime/manager . | ||
ENTRYPOINT ["/manager"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
build docker image | ||
|
||
```bash | ||
docker build -f ./crdexample/Dockerfile . | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
Copyright 2018 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"context" | ||
|
||
"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/runtime" | ||
"sigs.k8s.io/controller-runtime/crdexample/logutil" | ||
"sigs.k8s.io/controller-runtime/crdexample/pkg" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" | ||
"sigs.k8s.io/controller-runtime/pkg/reconcile" | ||
) | ||
|
||
var fmLog = logutil.Log.WithName("firstmate-reconciler") | ||
|
||
// FirstMateController reconciles ReplicaSets | ||
type FirstMateController struct { | ||
// client can be used to retrieve objects from the APIServer. | ||
client client.Client | ||
} | ||
|
||
func (i *FirstMateController) InjectClient(c client.Client) error { | ||
i.client = c | ||
return nil | ||
} | ||
|
||
// Implement reconcile.Reconciler so the controller can reconcile objects | ||
var _ reconcile.Reconciler = &FirstMateController{} | ||
|
||
func (r *FirstMateController) Reconcile(request reconcile.Request) (reconcile.Result, error) { | ||
// set up a entryLog object so we don't have to type request over and over again | ||
log := fmLog.WithValues("request", request) | ||
ctx := context.Background() | ||
|
||
// Fetch the firstMate from the cache | ||
fm := &pkg.FirstMate{} | ||
if err := r.client.Get(ctx, request.NamespacedName, fm); errors.IsNotFound(err) { | ||
return reconcile.Result{}, nil | ||
} else if err != nil { | ||
log.Error(err, "could not fetch firstMate") | ||
return reconcile.Result{}, err | ||
} | ||
|
||
dep := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: request.Name, Namespace: request.Namespace}} | ||
updateFn := (&createOrUpdateDeployment{firstMate: fm, log: fmLog}).do | ||
|
||
_, err := controllerutil.CreateOrUpdate(ctx, r.client, dep, updateFn) | ||
if err != nil { | ||
return reconcile.Result{}, err | ||
} | ||
|
||
return reconcile.Result{}, nil | ||
} | ||
|
||
type createOrUpdateDeployment struct { | ||
firstMate *pkg.FirstMate | ||
log logr.Logger | ||
} | ||
|
||
func (r *createOrUpdateDeployment) do(existing runtime.Object) error { | ||
r.log.Info("creating or updating deployment") | ||
dep := existing.(*appsv1.Deployment) | ||
dep.Labels = r.firstMate.Labels | ||
dep.Spec.Replicas = &r.firstMate.Spec.Crew | ||
dep.Spec.Template.Labels = r.firstMate.Labels | ||
dep.Spec.Selector.MatchLabels = r.firstMate.Labels | ||
dep.Spec.Template.Spec.Containers = []corev1.Container{{Name: "nginx", Image: "nginx"}} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
Copyright 2018 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package logutil | ||
|
||
import ( | ||
"github.com/go-logr/logr" | ||
|
||
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" | ||
) | ||
|
||
var Log logr.Logger | ||
|
||
func init() { | ||
logf.SetLogger(logf.ZapLogger(true)) | ||
Log = logf.Log.WithName("crew-controller") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
Copyright 2018 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"flag" | ||
"os" | ||
|
||
appsv1 "k8s.io/api/apps/v1" | ||
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp" | ||
"sigs.k8s.io/controller-runtime/crdexample/logutil" | ||
"sigs.k8s.io/controller-runtime/crdexample/pkg" | ||
"sigs.k8s.io/controller-runtime/pkg/builder" | ||
"sigs.k8s.io/controller-runtime/pkg/client/config" | ||
"sigs.k8s.io/controller-runtime/pkg/manager" | ||
"sigs.k8s.io/controller-runtime/pkg/runtime/signals" | ||
) | ||
|
||
func main() { | ||
flag.Parse() | ||
entryLog := logutil.Log.WithName("entrypoint") | ||
|
||
entryLog.Info("setting up manager") | ||
mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{Port: 12789}) | ||
if err != nil { | ||
entryLog.Error(err, "unable to set up overall controller manager") | ||
os.Exit(1) | ||
} | ||
|
||
entryLog.Info("setting up scheme") | ||
if err := pkg.AddToScheme(mgr.GetScheme()); err != nil { | ||
entryLog.Error(err, "unable add APIs to scheme") | ||
os.Exit(1) | ||
} | ||
|
||
entryLog.Info("setting up controllers") | ||
err = builder.ControllerManagedBy(mgr). | ||
For(&pkg.FirstMate{}). | ||
Owns(&appsv1.Deployment{}). | ||
Complete(&FirstMateController{}) | ||
if err != nil { | ||
entryLog.Error(err, "unable to set up controllers") | ||
os.Exit(1) | ||
} | ||
|
||
entryLog.Info("starting manager") | ||
if err := mgr.Start(signals.SetupSignalHandler()); err != nil { | ||
entryLog.Error(err, "unable to run manager") | ||
os.Exit(1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* | ||
Copyright 2018 The Kubernetes authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
// Package v1 contains API Schema definitions for the crew v1 API group | ||
// +k8s:openapi-gen=true | ||
// +k8s:deepcopy-gen=package,register | ||
// +k8s:conversion-gen=sigs.k8s.io/kubebuilder/test/project/pkg/apis/crew | ||
// +k8s:defaulter-gen=TypeMeta | ||
// +groupName=crew.example.com | ||
package pkg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
/* | ||
Copyright 2018 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package pkg | ||
|
||
import ( | ||
"fmt" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/apimachinery/pkg/runtime/schema" | ||
"sigs.k8s.io/controller-runtime/crdexample/logutil" | ||
"sigs.k8s.io/controller-runtime/pkg/scheme" | ||
"sigs.k8s.io/controller-runtime/pkg/webhook" | ||
) | ||
|
||
// +genclient | ||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||
|
||
var log = logutil.Log.WithName("firstmate-resource") | ||
|
||
// firstMate is the Schema for the firstmates API | ||
// +k8s:openapi-gen=true | ||
type FirstMate struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ObjectMeta `json:"metadata,omitempty"` | ||
|
||
Spec FirstMateSpec `json:"spec,omitempty"` | ||
Status FirstMateStatus `json:"status,omitempty"` | ||
} | ||
|
||
// FirstMateSpec defines the desired state of firstMate | ||
type FirstMateSpec struct { | ||
Height *int `json:"height,omitempty"` | ||
Experience int `json:"experience,omitempty"` | ||
Crew int32 `json:"crew,omitempty"` | ||
} | ||
|
||
// FirstMateStatus defines the observed state of firstMate | ||
type FirstMateStatus struct { | ||
Location string | ||
} | ||
|
||
var _ webhook.Validator = &FirstMate{} | ||
|
||
// ValidateCreate implements webhookutil.validator so a webhook will be registered for the type | ||
func (f *FirstMate) ValidateCreate() error { | ||
log.Info("validate create", "name", f.Name) | ||
|
||
if f.Spec.Crew <= 0 { | ||
return fmt.Errorf("crew must be greater than 0") | ||
} | ||
return nil | ||
} | ||
|
||
// ValidateUpdate implements webhookutil.validator so a webhook will be registered for the type | ||
func (f *FirstMate) ValidateUpdate(old runtime.Object) error { | ||
log.Info("validate update", "name", f.Name) | ||
|
||
if f.Spec.Crew <= 0 { | ||
return fmt.Errorf("crew must be greater than 0") | ||
} | ||
|
||
oldF, ok := old.(*FirstMate) | ||
if !ok { | ||
return fmt.Errorf("expect old object to be a %T instead of %T", oldF, old) | ||
} | ||
if f.Spec.Crew-oldF.Spec.Crew > 1 || oldF.Spec.Crew-f.Spec.Crew > 1 { | ||
return fmt.Errorf("crew must be greater than 0") | ||
} | ||
return nil | ||
} | ||
|
||
var _ webhook.Defaulter = &FirstMate{} | ||
|
||
// Default implements webhookutil.defaulter so a webhook will be registered for the type | ||
func (f *FirstMate) Default() { | ||
log.Info("default", "name", f.Name) | ||
|
||
if *f.Spec.Height == 0 { | ||
height := 10 | ||
f.Spec.Height = &height | ||
} | ||
} | ||
|
||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||
|
||
// FirstMateList contains a list of firstMate | ||
type FirstMateList struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ListMeta `json:"metadata,omitempty"` | ||
Items []FirstMate `json:"items"` | ||
} | ||
|
||
func init() { | ||
SchemeBuilder.Register(&FirstMate{}, &FirstMateList{}) | ||
} | ||
|
||
var ( | ||
// SchemeGroupVersion is group version used to register these objects | ||
SchemeGroupVersion = schema.GroupVersion{Group: "crew.example.com", Version: "v1"} | ||
|
||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme | ||
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} | ||
|
||
// AddToScheme is required by pkg/client/... | ||
AddToScheme = SchemeBuilder.AddToScheme | ||
) | ||
|
||
// Resource is required by pkg/client/listers/... | ||
func Resource(resource string) schema.GroupResource { | ||
return SchemeGroupVersion.WithResource(resource).GroupResource() | ||
} | ||
|
||
// TODO: figure out should we encourage the users to do a wrapper for a core type object. | ||
type MyPod struct { | ||
corev1.Pod | ||
} | ||
|
||
var _ webhook.Defaulter = &MyPod{} | ||
|
||
func (p *MyPod) Default() { | ||
log.Info("default", *p) | ||
} |
Oops, something went wrong.