mirror of
https://github.com/kubernetes/client-go.git
synced 2025-07-18 17:21:23 +00:00
client-go: remove TPR example
Kubernetes-commit: b34464241d61941b4331727fdca8927b574de25b
This commit is contained in:
parent
e21a2f60cf
commit
847cceef55
@ -19,10 +19,6 @@ for client-go.
|
|||||||
|
|
||||||
- [**Work queues**](./workqueue): Create a hotloop-free controller with the
|
- [**Work queues**](./workqueue): Create a hotloop-free controller with the
|
||||||
rate-limited workqueue and the [informer framework][informer].
|
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):
|
- [**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
|
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
|
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
Block a user