mirror of https://github.com/k3s-io/k3s
client-go: remove TPR example
parent
a9bf44101b
commit
b34464241d
|
@ -387,7 +387,6 @@ staging/src/k8s.io/client-go/discovery
|
|||
staging/src/k8s.io/client-go/examples/create-update-delete-deployment
|
||||
staging/src/k8s.io/client-go/examples/in-cluster-client-configuration
|
||||
staging/src/k8s.io/client-go/examples/out-of-cluster-client-configuration
|
||||
staging/src/k8s.io/client-go/examples/third-party-resources-deprecated
|
||||
staging/src/k8s.io/client-go/informers
|
||||
staging/src/k8s.io/client-go/informers/admissionregistration
|
||||
staging/src/k8s.io/client-go/informers/admissionregistration/v1alpha1
|
||||
|
|
|
@ -81,7 +81,7 @@ if grep -rq '// import "k8s.io/kubernetes/' 'staging/'; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
for EXAMPLE in vendor/k8s.io/client-go/examples/{in-cluster-client-configuration,out-of-cluster-client-configuration,third-party-resources-deprecated} vendor/k8s.io/apiextensions-apiserver/examples ; do
|
||||
for EXAMPLE in vendor/k8s.io/client-go/examples/{in-cluster-client-configuration,out-of-cluster-client-configuration} vendor/k8s.io/apiextensions-apiserver/examples ; do
|
||||
test -d "${EXAMPLE}" # make sure example is still there
|
||||
if go list -f '{{ join .Deps "\n" }}' "./${EXAMPLE}/..." | sort | uniq | grep -q k8s.io/client-go/plugin; then
|
||||
echo "${EXAMPLE} imports client-go plugins by default, but shouldn't."
|
||||
|
|
|
@ -19,10 +19,6 @@ for client-go.
|
|||
|
||||
- [**Work queues**](./workqueue): Create a hotloop-free controller with the
|
||||
rate-limited workqueue and the [informer framework][informer].
|
||||
- [**Third-party resources (deprecated)**](./third-party-resources-deprecated):
|
||||
Register a third-party resource type with the API, create/update/query this third-party
|
||||
type, and write a controller that drives the cluster state based on the changes to
|
||||
the third-party resources.
|
||||
- [**Custom Resource Definition (successor of TPR)**](https://git.k8s.io/apiextensions-apiserver/examples/client-go):
|
||||
Register a custom resource type with the API, create/update/query this custom
|
||||
type, and write a controller that drives the cluster state based on the changes to
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["main.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/examples/third-party-resources-deprecated/apis/tpr/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/examples/third-party-resources-deprecated/client:go_default_library",
|
||||
"//vendor/k8s.io/client-go/examples/third-party-resources-deprecated/controller:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "third-party-resources-deprecated",
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -1,46 +0,0 @@
|
|||
# Third Party Resources Example – Deprecated
|
||||
|
||||
**Note:** ThirdPartyResources are deprecated since 1.7. The successor is CustomResourceDefinition in the apiextensions.k8s.io API group.
|
||||
|
||||
This particular example demonstrates how to perform basic operations such as:
|
||||
|
||||
* How to register a new ThirdPartyResource (custom Resource type)
|
||||
* How to create/get/list instances of your new Resource type (update/delete/etc work as well but are not demonstrated)
|
||||
* How to setup a controller on Resource handling create/update/delete events
|
||||
|
||||
## Running
|
||||
|
||||
```
|
||||
# assumes you have a working kubeconfig, not required if operating in-cluster
|
||||
go run *.go -kubeconfig=$HOME/.kube/config
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
ThirdPartyResources can be used to implement custom Resource types for your Kubernetes cluster.
|
||||
These act like most other Resources in Kubernetes, and may be `kubectl apply`'d, etc.
|
||||
|
||||
Some example use cases:
|
||||
|
||||
* Provisioning/Management of external datastores/databases (eg. CloudSQL/RDS instances)
|
||||
* Higher level abstractions around Kubernetes primitives (eg. a single Resource to define an etcd cluster, backed by a Service and a ReplicationController)
|
||||
|
||||
## Defining types
|
||||
|
||||
Each instance of your ThirdPartyResource has an attached Spec, which should be defined via a `struct{}` to provide data format validation.
|
||||
In practice, this Spec is arbitrary key-value data that specifies the configuration/behavior of your Resource.
|
||||
|
||||
For example, if you were implementing a ThirdPartyResource for a Database, you might provide a DatabaseSpec like the following:
|
||||
|
||||
``` go
|
||||
type DatabaseSpec struct {
|
||||
Databases []string `json:"databases"`
|
||||
Users []User `json:"users"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Name string `json:"name"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
```
|
|
@ -1,37 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["types_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/github.com/google/gofuzz:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"register.go",
|
||||
"types.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
],
|
||||
)
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 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
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
var (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package.
|
||||
const GroupName = "tpr.client-go.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is the group version used to register these objects.
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group-qualified GroupResource.
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
// addKnownTypes adds the set of types defined in this package to the supplied scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Example{},
|
||||
&ExampleList{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 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
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
const ExampleResourcePlural = "examples"
|
||||
|
||||
type Example struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
Spec ExampleSpec `json:"spec"`
|
||||
Status ExampleStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
type ExampleSpec struct {
|
||||
Foo string `json:"foo"`
|
||||
Bar bool `json:"bar"`
|
||||
}
|
||||
|
||||
type ExampleStatus struct {
|
||||
State ExampleState `json:"state,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
type ExampleState string
|
||||
|
||||
const (
|
||||
ExampleStateCreated ExampleState = "Created"
|
||||
ExampleStateProcessed ExampleState = "Processed"
|
||||
)
|
||||
|
||||
type ExampleList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
Items []Example `json:"items"`
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 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
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/google/gofuzz"
|
||||
|
||||
apitesting "k8s.io/apimachinery/pkg/api/testing"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
)
|
||||
|
||||
var _ runtime.Object = &Example{}
|
||||
var _ metav1.ObjectMetaAccessor = &Example{}
|
||||
|
||||
var _ runtime.Object = &ExampleList{}
|
||||
var _ metav1.ListMetaAccessor = &ExampleList{}
|
||||
|
||||
func exampleFuzzerFuncs(t apitesting.TestingCommon) []interface{} {
|
||||
return []interface{}{
|
||||
func(obj *ExampleList, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj)
|
||||
obj.Items = make([]Example, c.Intn(10))
|
||||
for i := range obj.Items {
|
||||
c.Fuzz(&obj.Items[i])
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// TestRoundTrip tests that the third-party kinds can be marshaled and unmarshaled correctly to/from JSON
|
||||
// without the loss of information. Moreover, deep copy is tested.
|
||||
func TestRoundTrip(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
|
||||
AddToScheme(scheme)
|
||||
|
||||
seed := rand.Int63()
|
||||
fuzzerFuncs := apitesting.MergeFuzzerFuncs(t, apitesting.GenericFuzzerFuncs(t, codecs), exampleFuzzerFuncs(t))
|
||||
fuzzer := apitesting.FuzzerFor(fuzzerFuncs, rand.NewSource(seed))
|
||||
|
||||
apitesting.RoundTripSpecificKindWithoutProtobuf(t, SchemeGroupVersion.WithKind("Example"), scheme, codecs, fuzzer, nil)
|
||||
apitesting.RoundTripSpecificKindWithoutProtobuf(t, SchemeGroupVersion.WithKind("ExampleList"), scheme, codecs, fuzzer, nil)
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"client.go",
|
||||
"tpr.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/client-go/examples/third-party-resources-deprecated/apis/tpr/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
],
|
||||
)
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 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 client
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/rest"
|
||||
|
||||
tprv1 "k8s.io/client-go/examples/third-party-resources-deprecated/apis/tpr/v1"
|
||||
)
|
||||
|
||||
func NewClient(cfg *rest.Config) (*rest.RESTClient, *runtime.Scheme, error) {
|
||||
scheme := runtime.NewScheme()
|
||||
if err := tprv1.AddToScheme(scheme); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
config := *cfg
|
||||
config.GroupVersion = &tprv1.SchemeGroupVersion
|
||||
config.APIPath = "/apis"
|
||||
config.ContentType = runtime.ContentTypeJSON
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: serializer.NewCodecFactory(scheme)}
|
||||
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return client, scheme, nil
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 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 client
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
"k8s.io/api/extensions/v1beta1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
tprv1 "k8s.io/client-go/examples/third-party-resources-deprecated/apis/tpr/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
// Uncomment the following line to load the gcp plugin (only required to authenticate against GKE clusters).
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
||||
)
|
||||
|
||||
func CreateTPR(clientset kubernetes.Interface) error {
|
||||
tpr := &v1beta1.ThirdPartyResource{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "example." + tprv1.GroupName,
|
||||
},
|
||||
Versions: []v1beta1.APIVersion{
|
||||
{Name: tprv1.SchemeGroupVersion.Version},
|
||||
},
|
||||
Description: "An Example ThirdPartyResource",
|
||||
}
|
||||
_, err := clientset.ExtensionsV1beta1().ThirdPartyResources().Create(tpr)
|
||||
return err
|
||||
}
|
||||
|
||||
func WaitForExampleResource(exampleClient *rest.RESTClient) error {
|
||||
return wait.Poll(100*time.Millisecond, 60*time.Second, func() (bool, error) {
|
||||
_, err := exampleClient.Get().Namespace(apiv1.NamespaceDefault).Resource(tprv1.ExampleResourcePlural).DoRaw()
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if apierrors.IsNotFound(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
})
|
||||
}
|
||||
|
||||
func WaitForExampleInstanceProcessed(exampleClient *rest.RESTClient, name string) error {
|
||||
return wait.Poll(100*time.Millisecond, 10*time.Second, func() (bool, error) {
|
||||
var example tprv1.Example
|
||||
err := exampleClient.Get().
|
||||
Resource(tprv1.ExampleResourcePlural).
|
||||
Namespace(apiv1.NamespaceDefault).
|
||||
Name(name).
|
||||
Do().Into(&example)
|
||||
|
||||
if err == nil && example.Status.State == tprv1.ExampleStateProcessed {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, err
|
||||
})
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["controller.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/client-go/examples/third-party-resources-deprecated/apis/tpr/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
|
||||
],
|
||||
)
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 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 controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
tprv1 "k8s.io/client-go/examples/third-party-resources-deprecated/apis/tpr/v1"
|
||||
)
|
||||
|
||||
// Watcher is an example of watching on resource create/update/delete events
|
||||
type ExampleController struct {
|
||||
ExampleClient *rest.RESTClient
|
||||
ExampleScheme *runtime.Scheme
|
||||
}
|
||||
|
||||
// Run starts an Example resource controller
|
||||
func (c *ExampleController) Run(ctx context.Context) error {
|
||||
fmt.Print("Watch Example objects\n")
|
||||
|
||||
// Watch Example objects
|
||||
_, err := c.watchExamples(ctx)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to register watch for Example resource: %v\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
<-ctx.Done()
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
func (c *ExampleController) watchExamples(ctx context.Context) (cache.Controller, error) {
|
||||
source := cache.NewListWatchFromClient(
|
||||
c.ExampleClient,
|
||||
tprv1.ExampleResourcePlural,
|
||||
apiv1.NamespaceAll,
|
||||
fields.Everything())
|
||||
|
||||
_, controller := cache.NewInformer(
|
||||
source,
|
||||
|
||||
// The object type.
|
||||
&tprv1.Example{},
|
||||
|
||||
// resyncPeriod
|
||||
// Every resyncPeriod, all resources in the cache will retrigger events.
|
||||
// Set to 0 to disable the resync.
|
||||
0,
|
||||
|
||||
// Your custom resource event handlers.
|
||||
cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.onAdd,
|
||||
UpdateFunc: c.onUpdate,
|
||||
DeleteFunc: c.onDelete,
|
||||
})
|
||||
|
||||
go controller.Run(ctx.Done())
|
||||
return controller, nil
|
||||
}
|
||||
|
||||
func (c *ExampleController) onAdd(obj interface{}) {
|
||||
example := obj.(*tprv1.Example)
|
||||
fmt.Printf("[CONTROLLER] OnAdd %s\n", example.ObjectMeta.SelfLink)
|
||||
|
||||
// NEVER modify objects from the store. It's a read-only, local cache.
|
||||
// You can use exampleScheme.Copy() to make a deep copy of original object and modify this copy
|
||||
// Or create a copy manually for better performance
|
||||
copyObj, err := c.ExampleScheme.Copy(example)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR creating a deep copy of example object: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
exampleCopy := copyObj.(*tprv1.Example)
|
||||
exampleCopy.Status = tprv1.ExampleStatus{
|
||||
State: tprv1.ExampleStateProcessed,
|
||||
Message: "Successfully processed by controller",
|
||||
}
|
||||
|
||||
err = c.ExampleClient.Put().
|
||||
Name(example.ObjectMeta.Name).
|
||||
Namespace(example.ObjectMeta.Namespace).
|
||||
Resource(tprv1.ExampleResourcePlural).
|
||||
Body(exampleCopy).
|
||||
Do().
|
||||
Error()
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR updating status: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("UPDATED status: %#v\n", exampleCopy)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ExampleController) onUpdate(oldObj, newObj interface{}) {
|
||||
oldExample := oldObj.(*tprv1.Example)
|
||||
newExample := newObj.(*tprv1.Example)
|
||||
fmt.Printf("[CONTROLLER] OnUpdate oldObj: %s\n", oldExample.ObjectMeta.SelfLink)
|
||||
fmt.Printf("[CONTROLLER] OnUpdate newObj: %s\n", newExample.ObjectMeta.SelfLink)
|
||||
}
|
||||
|
||||
func (c *ExampleController) onDelete(obj interface{}) {
|
||||
example := obj.(*tprv1.Example)
|
||||
fmt.Printf("[CONTROLLER] OnDelete %s\n", example.ObjectMeta.SelfLink)
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 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.
|
||||
*/
|
||||
|
||||
// Note: the example only works with the code within the same release/branch.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
||||
// Uncomment the following line to load the gcp plugin (only required to authenticate against GKE clusters).
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
||||
|
||||
tprv1 "k8s.io/client-go/examples/third-party-resources-deprecated/apis/tpr/v1"
|
||||
exampleclient "k8s.io/client-go/examples/third-party-resources-deprecated/client"
|
||||
examplecontroller "k8s.io/client-go/examples/third-party-resources-deprecated/controller"
|
||||
)
|
||||
|
||||
func main() {
|
||||
kubeconfig := flag.String("kubeconfig", "", "Path to a kube config. Only required if out-of-cluster.")
|
||||
flag.Parse()
|
||||
|
||||
// Create the client config. Use kubeconfig if given, otherwise assume in-cluster.
|
||||
config, err := buildConfig(*kubeconfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
clientset, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// initialize third party resource if it does not exist
|
||||
err = exampleclient.CreateTPR(clientset)
|
||||
if err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// make a new config for our extension's API group, using the first config as a baseline
|
||||
exampleClient, exampleScheme, err := exampleclient.NewClient(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// wait until TPR gets processed
|
||||
err = exampleclient.WaitForExampleResource(exampleClient)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// start a controller on instances of our TPR
|
||||
controller := examplecontroller.ExampleController{
|
||||
ExampleClient: exampleClient,
|
||||
ExampleScheme: exampleScheme,
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
go controller.Run(ctx)
|
||||
|
||||
// Create an instance of our TPR
|
||||
example := &tprv1.Example{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "example1",
|
||||
},
|
||||
Spec: tprv1.ExampleSpec{
|
||||
Foo: "hello",
|
||||
Bar: true,
|
||||
},
|
||||
Status: tprv1.ExampleStatus{
|
||||
State: tprv1.ExampleStateCreated,
|
||||
Message: "Created, not processed yet",
|
||||
},
|
||||
}
|
||||
var result tprv1.Example
|
||||
err = exampleClient.Post().
|
||||
Resource(tprv1.ExampleResourcePlural).
|
||||
Namespace(apiv1.NamespaceDefault).
|
||||
Body(example).
|
||||
Do().Into(&result)
|
||||
if err == nil {
|
||||
fmt.Printf("CREATED: %#v\n", result)
|
||||
} else if apierrors.IsAlreadyExists(err) {
|
||||
fmt.Printf("ALREADY EXISTS: %#v\n", result)
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Poll until Example object is handled by controller and gets status updated to "Processed"
|
||||
err = exampleclient.WaitForExampleInstanceProcessed(exampleClient, "example1")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Print("PROCESSED\n")
|
||||
|
||||
// Fetch a list of our TPRs
|
||||
exampleList := tprv1.ExampleList{}
|
||||
err = exampleClient.Get().Resource(tprv1.ExampleResourcePlural).Do().Into(&exampleList)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("LIST: %#v\n", exampleList)
|
||||
}
|
||||
|
||||
func buildConfig(kubeconfig string) (*rest.Config, error) {
|
||||
if kubeconfig != "" {
|
||||
return clientcmd.BuildConfigFromFlags("", kubeconfig)
|
||||
}
|
||||
return rest.InClusterConfig()
|
||||
}
|
Loading…
Reference in New Issue