mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	ThirdPartyResource client-go example: added TPR controller example, code cleanup and integration test
This commit is contained in:
		@@ -339,6 +339,7 @@ staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth
 | 
			
		||||
staging/src/k8s.io/client-go/discovery
 | 
			
		||||
staging/src/k8s.io/client-go/examples/in-cluster
 | 
			
		||||
staging/src/k8s.io/client-go/examples/out-of-cluster
 | 
			
		||||
staging/src/k8s.io/client-go/examples/third-party-resources
 | 
			
		||||
staging/src/k8s.io/client-go/informers
 | 
			
		||||
staging/src/k8s.io/client-go/informers/apps
 | 
			
		||||
staging/src/k8s.io/client-go/informers/apps/v1beta1
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,6 @@ load(
 | 
			
		||||
    "@io_bazel_rules_go//go:def.bzl",
 | 
			
		||||
    "go_binary",
 | 
			
		||||
    "go_library",
 | 
			
		||||
    "go_test",
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
go_binary(
 | 
			
		||||
@@ -15,34 +14,18 @@ go_binary(
 | 
			
		||||
    tags = ["automanaged"],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
go_test(
 | 
			
		||||
    name = "go_default_test",
 | 
			
		||||
    srcs = ["types_test.go"],
 | 
			
		||||
    library = ":go_default_library",
 | 
			
		||||
    tags = ["automanaged"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
go_library(
 | 
			
		||||
    name = "go_default_library",
 | 
			
		||||
    srcs = [
 | 
			
		||||
        "main.go",
 | 
			
		||||
        "types.go",
 | 
			
		||||
    ],
 | 
			
		||||
    srcs = ["main.go"],
 | 
			
		||||
    tags = ["automanaged"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//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/schema:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/examples/third-party-resources/apis/tpr/v1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/examples/third-party-resources/client:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/examples/third-party-resources/controller:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/kubernetes:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/pkg/api/v1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/pkg/apis/extensions/v1beta1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/rest:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ 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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,34 @@
 | 
			
		||||
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/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/apimachinery/pkg/runtime: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",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
@@ -0,0 +1,56 @@
 | 
			
		||||
/*
 | 
			
		||||
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 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()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	// We only register manually written functions here. The registration of the
 | 
			
		||||
	// generated functions takes place in the generated files. The separation
 | 
			
		||||
	// makes the code compile even when the generated files are missing.
 | 
			
		||||
	SchemeBuilder.Register(addKnownTypes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Adds the list of known types to api.Scheme.
 | 
			
		||||
func addKnownTypes(scheme *runtime.Scheme) error {
 | 
			
		||||
	scheme.AddKnownTypes(SchemeGroupVersion,
 | 
			
		||||
		&Example{},
 | 
			
		||||
		&ExampleList{},
 | 
			
		||||
	)
 | 
			
		||||
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,53 @@
 | 
			
		||||
/*
 | 
			
		||||
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"`
 | 
			
		||||
}
 | 
			
		||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
package v1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
@@ -0,0 +1,29 @@
 | 
			
		||||
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/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/apis/tpr/v1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/kubernetes:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/pkg/api/v1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/pkg/apis/extensions/v1beta1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/rest:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
@@ -0,0 +1,45 @@
 | 
			
		||||
/*
 | 
			
		||||
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/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
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,76 @@
 | 
			
		||||
/*
 | 
			
		||||
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"
 | 
			
		||||
 | 
			
		||||
	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/apis/tpr/v1"
 | 
			
		||||
	"k8s.io/client-go/kubernetes"
 | 
			
		||||
	apiv1 "k8s.io/client-go/pkg/api/v1"
 | 
			
		||||
	"k8s.io/client-go/pkg/apis/extensions/v1beta1"
 | 
			
		||||
	"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
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,22 @@
 | 
			
		||||
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/apimachinery/pkg/fields:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/examples/third-party-resources/apis/tpr/v1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/pkg/api/v1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/rest:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/tools/cache:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
@@ -0,0 +1,126 @@
 | 
			
		||||
/*
 | 
			
		||||
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"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apimachinery/pkg/fields"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	apiv1 "k8s.io/client-go/pkg/api/v1"
 | 
			
		||||
	"k8s.io/client-go/rest"
 | 
			
		||||
	"k8s.io/client-go/tools/cache"
 | 
			
		||||
 | 
			
		||||
	tprv1 "k8s.io/client-go/examples/third-party-resources/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)
 | 
			
		||||
}
 | 
			
		||||
@@ -18,22 +18,23 @@ limitations under the License.
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apimachinery/pkg/api/errors"
 | 
			
		||||
	apierrors "k8s.io/apimachinery/pkg/api/errors"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/serializer"
 | 
			
		||||
	"k8s.io/client-go/kubernetes"
 | 
			
		||||
	"k8s.io/client-go/kubernetes/scheme"
 | 
			
		||||
	"k8s.io/client-go/pkg/api/v1"
 | 
			
		||||
	"k8s.io/client-go/pkg/apis/extensions/v1beta1"
 | 
			
		||||
	apiv1 "k8s.io/client-go/pkg/api/v1"
 | 
			
		||||
	"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/apis/tpr/v1"
 | 
			
		||||
	exampleclient "k8s.io/client-go/examples/third-party-resources/client"
 | 
			
		||||
	examplecontroller "k8s.io/client-go/examples/third-party-resources/controller"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
@@ -52,83 +53,71 @@ func main() {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// initialize third party resource if it does not exist
 | 
			
		||||
	tpr, err := clientset.ExtensionsV1beta1().ThirdPartyResources().Get("example.k8s.io", metav1.GetOptions{})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.IsNotFound(err) {
 | 
			
		||||
			tpr := &v1beta1.ThirdPartyResource{
 | 
			
		||||
				ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
					Name: "example.k8s.io",
 | 
			
		||||
				},
 | 
			
		||||
				Versions: []v1beta1.APIVersion{
 | 
			
		||||
					{Name: "v1"},
 | 
			
		||||
				},
 | 
			
		||||
				Description: "An Example ThirdPartyResource",
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			result, err := clientset.ExtensionsV1beta1().ThirdPartyResources().Create(tpr)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
	err = exampleclient.CreateTPR(clientset)
 | 
			
		||||
	if err != nil && !apierrors.IsAlreadyExists(err) {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
			fmt.Printf("CREATED: %#v\nFROM: %#v\n", result, tpr)
 | 
			
		||||
		} else {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		fmt.Printf("SKIPPING: already exists %#v\n", tpr)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// make a new config for our extension's API group, using the first config as a baseline
 | 
			
		||||
	var tprconfig *rest.Config
 | 
			
		||||
	tprconfig = config
 | 
			
		||||
	configureClient(tprconfig)
 | 
			
		||||
 | 
			
		||||
	tprclient, err := rest.RESTClientFor(tprconfig)
 | 
			
		||||
	exampleClient, exampleScheme, err := exampleclient.NewClient(config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var example Example
 | 
			
		||||
 | 
			
		||||
	err = tprclient.Get().
 | 
			
		||||
		Resource("examples").
 | 
			
		||||
		Namespace(v1.NamespaceDefault).
 | 
			
		||||
		Name("example1").
 | 
			
		||||
		Do().Into(&example)
 | 
			
		||||
 | 
			
		||||
	// wait until TPR gets processed
 | 
			
		||||
	err = exampleclient.WaitForExampleResource(exampleClient)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.IsNotFound(err) {
 | 
			
		||||
		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 := &Example{
 | 
			
		||||
				Metadata: metav1.ObjectMeta{
 | 
			
		||||
	example := &tprv1.Example{
 | 
			
		||||
		ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
			Name: "example1",
 | 
			
		||||
		},
 | 
			
		||||
				Spec: ExampleSpec{
 | 
			
		||||
		Spec: tprv1.ExampleSpec{
 | 
			
		||||
			Foo: "hello",
 | 
			
		||||
			Bar: true,
 | 
			
		||||
		},
 | 
			
		||||
		Status: tprv1.ExampleStatus{
 | 
			
		||||
			State:   tprv1.ExampleStateCreated,
 | 
			
		||||
			Message: "Created, not processed yet",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
			var result Example
 | 
			
		||||
			err = tprclient.Post().
 | 
			
		||||
				Resource("examples").
 | 
			
		||||
				Namespace(v1.NamespaceDefault).
 | 
			
		||||
	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.Printf("CREATED: %#v\n", result)
 | 
			
		||||
		} else {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		fmt.Printf("GET: %#v\n", example)
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Print("PROCESSED\n")
 | 
			
		||||
 | 
			
		||||
	// Fetch a list of our TPRs
 | 
			
		||||
	exampleList := ExampleList{}
 | 
			
		||||
	err = tprclient.Get().Resource("examples").Do().Into(&exampleList)
 | 
			
		||||
	exampleList := tprv1.ExampleList{}
 | 
			
		||||
	err = exampleClient.Get().Resource(tprv1.ExampleResourcePlural).Do().Into(&exampleList)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
@@ -141,27 +130,3 @@ func buildConfig(kubeconfig string) (*rest.Config, error) {
 | 
			
		||||
	}
 | 
			
		||||
	return rest.InClusterConfig()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func configureClient(config *rest.Config) {
 | 
			
		||||
	groupversion := schema.GroupVersion{
 | 
			
		||||
		Group:   "k8s.io",
 | 
			
		||||
		Version: "v1",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config.GroupVersion = &groupversion
 | 
			
		||||
	config.APIPath = "/apis"
 | 
			
		||||
	config.ContentType = runtime.ContentTypeJSON
 | 
			
		||||
	config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
 | 
			
		||||
 | 
			
		||||
	schemeBuilder := runtime.NewSchemeBuilder(
 | 
			
		||||
		func(scheme *runtime.Scheme) error {
 | 
			
		||||
			scheme.AddKnownTypes(
 | 
			
		||||
				groupversion,
 | 
			
		||||
				&Example{},
 | 
			
		||||
				&ExampleList{},
 | 
			
		||||
			)
 | 
			
		||||
			return nil
 | 
			
		||||
		})
 | 
			
		||||
	metav1.AddToGroupVersion(scheme.Scheme, groupversion)
 | 
			
		||||
	schemeBuilder.AddToScheme(scheme.Scheme)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,92 +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 main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ExampleSpec struct {
 | 
			
		||||
	Foo string `json:"foo"`
 | 
			
		||||
	Bar bool   `json:"bar"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Example struct {
 | 
			
		||||
	metav1.TypeMeta `json:",inline"`
 | 
			
		||||
	Metadata        metav1.ObjectMeta `json:"metadata"`
 | 
			
		||||
 | 
			
		||||
	Spec ExampleSpec `json:"spec"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ExampleList struct {
 | 
			
		||||
	metav1.TypeMeta `json:",inline"`
 | 
			
		||||
	Metadata        metav1.ListMeta `json:"metadata"`
 | 
			
		||||
 | 
			
		||||
	Items []Example `json:"items"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Required to satisfy Object interface
 | 
			
		||||
func (e *Example) GetObjectKind() schema.ObjectKind {
 | 
			
		||||
	return &e.TypeMeta
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Required to satisfy ObjectMetaAccessor interface
 | 
			
		||||
func (e *Example) GetObjectMeta() metav1.Object {
 | 
			
		||||
	return &e.Metadata
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Required to satisfy Object interface
 | 
			
		||||
func (el *ExampleList) GetObjectKind() schema.ObjectKind {
 | 
			
		||||
	return &el.TypeMeta
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Required to satisfy ListMetaAccessor interface
 | 
			
		||||
func (el *ExampleList) GetListMeta() metav1.List {
 | 
			
		||||
	return &el.Metadata
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// The code below is used only to work around a known problem with third-party
 | 
			
		||||
// resources and ugorji. If/when these issues are resolved, the code below
 | 
			
		||||
// should no longer be required.
 | 
			
		||||
 | 
			
		||||
type ExampleListCopy ExampleList
 | 
			
		||||
type ExampleCopy Example
 | 
			
		||||
 | 
			
		||||
func (e *Example) UnmarshalJSON(data []byte) error {
 | 
			
		||||
	tmp := ExampleCopy{}
 | 
			
		||||
	err := json.Unmarshal(data, &tmp)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	tmp2 := Example(tmp)
 | 
			
		||||
	*e = tmp2
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (el *ExampleList) UnmarshalJSON(data []byte) error {
 | 
			
		||||
	tmp := ExampleListCopy{}
 | 
			
		||||
	err := json.Unmarshal(data, &tmp)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	tmp2 := ExampleList(tmp)
 | 
			
		||||
	*el = tmp2
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								test/integration/thirdparty/BUILD
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								test/integration/thirdparty/BUILD
									
									
									
									
										vendored
									
									
								
							@@ -9,7 +9,10 @@ load(
 | 
			
		||||
 | 
			
		||||
go_test(
 | 
			
		||||
    name = "go_default_test",
 | 
			
		||||
    srcs = ["thirdparty_test.go"],
 | 
			
		||||
    srcs = [
 | 
			
		||||
        "client-go_test.go",
 | 
			
		||||
        "thirdparty_test.go",
 | 
			
		||||
    ],
 | 
			
		||||
    tags = [
 | 
			
		||||
        "automanaged",
 | 
			
		||||
        "integration",
 | 
			
		||||
@@ -21,9 +24,16 @@ go_test(
 | 
			
		||||
        "//test/integration/framework: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/schema:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/examples/third-party-resources/apis/tpr/v1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/examples/third-party-resources/client:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/examples/third-party-resources/controller:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/kubernetes:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/pkg/api/v1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/client-go/rest:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										109
									
								
								test/integration/thirdparty/client-go_test.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								test/integration/thirdparty/client-go_test.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
			
		||||
/*
 | 
			
		||||
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 thirdparty
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/serializer"
 | 
			
		||||
	"k8s.io/client-go/kubernetes"
 | 
			
		||||
	apiv1 "k8s.io/client-go/pkg/api/v1"
 | 
			
		||||
	"k8s.io/client-go/rest"
 | 
			
		||||
	"k8s.io/kubernetes/test/integration/framework"
 | 
			
		||||
 | 
			
		||||
	exampletprv1 "k8s.io/client-go/examples/third-party-resources/apis/tpr/v1"
 | 
			
		||||
	exampleclient "k8s.io/client-go/examples/third-party-resources/client"
 | 
			
		||||
	examplecontroller "k8s.io/client-go/examples/third-party-resources/controller"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestClientGoThirdPartyResourceExample(t *testing.T) {
 | 
			
		||||
	_, s := framework.RunAMaster(framework.NewIntegrationTestMasterConfig())
 | 
			
		||||
	defer s.Close()
 | 
			
		||||
 | 
			
		||||
	scheme := runtime.NewScheme()
 | 
			
		||||
	if err := exampletprv1.AddToScheme(scheme); err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config := &rest.Config{Host: s.URL, ContentConfig: rest.ContentConfig{
 | 
			
		||||
		NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: serializer.NewCodecFactory(scheme)},
 | 
			
		||||
	}}
 | 
			
		||||
	clientset, err := kubernetes.NewForConfig(config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.Logf("Creating TPR %q", exampletprv1.ExampleResourcePlural)
 | 
			
		||||
	if err := exampleclient.CreateTPR(clientset); err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error creating the ThirdPartyResource: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	exampleClient, exampleScheme, err := exampleclient.NewClient(config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.Logf("Waiting for TPR %q to show up", exampletprv1.ExampleResourcePlural)
 | 
			
		||||
	if err := exampleclient.WaitForExampleResource(exampleClient); err != nil {
 | 
			
		||||
		t.Fatalf("TPR examples did not show up: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	t.Logf("TPR %q is active", exampletprv1.ExampleResourcePlural)
 | 
			
		||||
 | 
			
		||||
	t.Logf("Starting a controller on instances of TPR %q", exampletprv1.ExampleResourcePlural)
 | 
			
		||||
	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
 | 
			
		||||
	t.Logf("Creating instance of TPR %q", exampletprv1.ExampleResourcePlural)
 | 
			
		||||
	example := &exampletprv1.Example{
 | 
			
		||||
		ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
			Name: "example1",
 | 
			
		||||
		},
 | 
			
		||||
		Spec: exampletprv1.ExampleSpec{
 | 
			
		||||
			Foo: "hello",
 | 
			
		||||
			Bar: true,
 | 
			
		||||
		},
 | 
			
		||||
		Status: exampletprv1.ExampleStatus{
 | 
			
		||||
			State:   exampletprv1.ExampleStateCreated,
 | 
			
		||||
			Message: "Created, not processed yet",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	var result exampletprv1.Example
 | 
			
		||||
	err = exampleClient.Post().
 | 
			
		||||
		Resource(exampletprv1.ExampleResourcePlural).
 | 
			
		||||
		Namespace(apiv1.NamespaceDefault).
 | 
			
		||||
		Body(example).
 | 
			
		||||
		Do().Into(&result)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed to create an instance of TPR: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.Logf("Waiting for TPR %q instance to be processed", exampletprv1.ExampleResourcePlural)
 | 
			
		||||
	if err := exampleclient.WaitForExampleInstanceProcessed(exampleClient, "example1"); err != nil {
 | 
			
		||||
		t.Fatalf("TPR example was not processed correctly: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	t.Logf("TPR %q instance is processed", exampletprv1.ExampleResourcePlural)
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user