mirror of https://github.com/k3s-io/k3s
Merge pull request #47050 from sttts/sttts-deprecate-tpr-example
Automatic merge from submit-queue (batch tested with PRs 47024, 47050, 47086, 47081, 47013) client-go: deprecate TPR example and add CRD example /cc @nilebox Part of https://github.com/kubernetes/kubernetes/issues/46702pull/6/head
commit
43295501a3
|
@ -324,6 +324,7 @@ plugin/pkg/scheduler/algorithmprovider
|
|||
plugin/pkg/scheduler/algorithmprovider/defaults
|
||||
plugin/pkg/scheduler/api/validation
|
||||
staging/src/k8s.io/apiextensions-apiserver
|
||||
staging/src/k8s.io/apiextensions-apiserver/examples/client-go
|
||||
staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install
|
||||
staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation
|
||||
staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions
|
||||
|
@ -384,7 +385,7 @@ 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
|
||||
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/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
|
||||
|
|
|
@ -80,7 +80,7 @@ if grep -rq '// import "k8s.io/kubernetes/' 'staging/'; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
for EXAMPLE in vendor/k8s.io/client-go/examples/{in-cluster,out-of-cluster,third-party-resources}; do
|
||||
for EXAMPLE in vendor/k8s.io/client-go/examples/{in-cluster,out-of-cluster,third-party-resources-deprecated} 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."
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
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/apiextensions-apiserver/examples/client-go/apis/cr/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/examples/client-go/client:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/examples/client-go/controller:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset: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/pkg/api/v1: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 = "client-go",
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -0,0 +1,46 @@
|
|||
# Custom Resource Example
|
||||
|
||||
**Note:** CustomResourceDefinition is the successor of the deprecated ThirdPartyResource.
|
||||
|
||||
This particular example demonstrates how to perform basic operations such as:
|
||||
|
||||
* How to register a new custom resource (custom resource type) using a CustomResourceDefinition
|
||||
* 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
|
||||
|
||||
CustomResourceDefinitions 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 custom resource 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 custom resource 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"`
|
||||
}
|
||||
```
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
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 used in this package.
|
||||
const GroupName = "cr.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
|
||||
}
|
|
@ -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",
|
||||
"cr.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/apiextensions-apiserver/examples/client-go/apis/cr/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset: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/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/client-go/pkg/api/v1: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"
|
||||
|
||||
crv1 "k8s.io/apiextensions-apiserver/examples/client-go/apis/cr/v1"
|
||||
)
|
||||
|
||||
func NewClient(cfg *rest.Config) (*rest.RESTClient, *runtime.Scheme, error) {
|
||||
scheme := runtime.NewScheme()
|
||||
if err := crv1.AddToScheme(scheme); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
config := *cfg
|
||||
config.GroupVersion = &crv1.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,103 @@
|
|||
/*
|
||||
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 (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
crv1 "k8s.io/apiextensions-apiserver/examples/client-go/apis/cr/v1"
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||
"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"
|
||||
)
|
||||
|
||||
const exampleCRDName = crv1.ExampleResourcePlural + "." + crv1.GroupName
|
||||
|
||||
func CreateCustomResourceDefinition(clientset apiextensionsclient.Interface) (*apiextensionsv1beta1.CustomResourceDefinition, error) {
|
||||
crd := &apiextensionsv1beta1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: exampleCRDName,
|
||||
},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: crv1.GroupName,
|
||||
Version: crv1.SchemeGroupVersion.Version,
|
||||
Scope: apiextensionsv1beta1.NamespaceScoped,
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
Plural: crv1.ExampleResourcePlural,
|
||||
Kind: reflect.TypeOf(crv1.Example{}).Name(),
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// wait for CRD being established
|
||||
err = wait.Poll(500*time.Millisecond, 60*time.Second, func() (bool, error) {
|
||||
crd, err = clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Get(exampleCRDName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, cond := range crd.Status.Conditions {
|
||||
switch cond.Type {
|
||||
case apiextensionsv1beta1.Established:
|
||||
if cond.Status == apiextensionsv1beta1.ConditionTrue {
|
||||
return true, err
|
||||
}
|
||||
case apiextensionsv1beta1.NamesAccepted:
|
||||
if cond.Status == apiextensionsv1beta1.ConditionFalse {
|
||||
fmt.Printf("Name conflict: %v\n", cond.Reason)
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, err
|
||||
})
|
||||
if err != nil {
|
||||
deleteErr := clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Delete(exampleCRDName, nil)
|
||||
if deleteErr != nil {
|
||||
return nil, errors.NewAggregate([]error{err, deleteErr})
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return crd, nil
|
||||
}
|
||||
|
||||
func WaitForExampleInstanceProcessed(exampleClient *rest.RESTClient, name string) error {
|
||||
return wait.Poll(100*time.Millisecond, 10*time.Second, func() (bool, error) {
|
||||
var example crv1.Example
|
||||
err := exampleClient.Get().
|
||||
Resource(crv1.ExampleResourcePlural).
|
||||
Namespace(apiv1.NamespaceDefault).
|
||||
Name(name).
|
||||
Do().Into(&example)
|
||||
|
||||
if err == nil && example.Status.State == crv1.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/apiextensions-apiserver/examples/client-go/apis/cr/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/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"
|
||||
|
||||
crv1 "k8s.io/apiextensions-apiserver/examples/client-go/apis/cr/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,
|
||||
crv1.ExampleResourcePlural,
|
||||
apiv1.NamespaceAll,
|
||||
fields.Everything())
|
||||
|
||||
_, controller := cache.NewInformer(
|
||||
source,
|
||||
|
||||
// The object type.
|
||||
&crv1.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.(*crv1.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.(*crv1.Example)
|
||||
exampleCopy.Status = crv1.ExampleStatus{
|
||||
State: crv1.ExampleStateProcessed,
|
||||
Message: "Successfully processed by controller",
|
||||
}
|
||||
|
||||
err = c.ExampleClient.Put().
|
||||
Name(example.ObjectMeta.Name).
|
||||
Namespace(example.ObjectMeta.Namespace).
|
||||
Resource(crv1.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.(*crv1.Example)
|
||||
newExample := newObj.(*crv1.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.(*crv1.Example)
|
||||
fmt.Printf("[CONTROLLER] OnDelete %s\n", example.ObjectMeta.SelfLink)
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
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"
|
||||
|
||||
crv1 "k8s.io/apiextensions-apiserver/examples/client-go/apis/cr/v1"
|
||||
exampleclient "k8s.io/apiextensions-apiserver/examples/client-go/client"
|
||||
examplecontroller "k8s.io/apiextensions-apiserver/examples/client-go/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)
|
||||
}
|
||||
|
||||
apiextensionsclientset, err := apiextensionsclient.NewForConfig(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// initialize custom resource using a CustomResourceDefinition if it does not exist
|
||||
crd, err := exampleclient.CreateCustomResourceDefinition(apiextensionsclientset)
|
||||
if err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
panic(err)
|
||||
}
|
||||
defer apiextensionsclientset.ApiextensionsV1beta1().CustomResourceDefinitions().Delete(crd.Name, nil)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// start a controller on instances of our custom resource
|
||||
controller := examplecontroller.ExampleController{
|
||||
ExampleClient: exampleClient,
|
||||
ExampleScheme: exampleScheme,
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
go controller.Run(ctx)
|
||||
|
||||
// Create an instance of our custom resource
|
||||
example := &crv1.Example{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "example1",
|
||||
},
|
||||
Spec: crv1.ExampleSpec{
|
||||
Foo: "hello",
|
||||
Bar: true,
|
||||
},
|
||||
Status: crv1.ExampleStatus{
|
||||
State: crv1.ExampleStateCreated,
|
||||
Message: "Created, not processed yet",
|
||||
},
|
||||
}
|
||||
var result crv1.Example
|
||||
err = exampleClient.Post().
|
||||
Resource(crv1.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 := crv1.ExampleList{}
|
||||
err = exampleClient.Get().Resource(crv1.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()
|
||||
}
|
|
@ -11,6 +11,7 @@ go_test(
|
|||
name = "go_default_test",
|
||||
srcs = [
|
||||
"basic_test.go",
|
||||
"client-go_test.go",
|
||||
"finalization_test.go",
|
||||
"registration_test.go",
|
||||
"validation_test.go",
|
||||
|
@ -22,6 +23,9 @@ go_test(
|
|||
deps = [
|
||||
"//vendor/github.com/coreos/etcd/clientv3:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/examples/client-go/apis/cr/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/examples/client-go/client:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/examples/client-go/controller:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/apiserver:go_default_library",
|
||||
"//vendor/k8s.io/apiextensions-apiserver/test/integration/testserver:go_default_library",
|
||||
|
@ -33,5 +37,6 @@ go_test(
|
|||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
||||
"//vendor/k8s.io/client-go/pkg/api/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
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 integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/test/integration/testserver"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||
|
||||
examplecrv1 "k8s.io/apiextensions-apiserver/examples/client-go/apis/cr/v1"
|
||||
exampleclient "k8s.io/apiextensions-apiserver/examples/client-go/client"
|
||||
examplecontroller "k8s.io/apiextensions-apiserver/examples/client-go/controller"
|
||||
)
|
||||
|
||||
func TestClientGoCustomResourceExample(t *testing.T) {
|
||||
t.Logf("Creating apiextensions apiserver")
|
||||
config, err := testserver.DefaultServerConfig()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
stopCh, apiExtensionClient, _, err := testserver.StartServer(config)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
defer close(stopCh)
|
||||
|
||||
t.Logf("Creating CustomResourceDefinition")
|
||||
crd, err := exampleclient.CreateCustomResourceDefinition(apiExtensionClient)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error creating the CustomResourceDefinition: %v", err)
|
||||
}
|
||||
defer apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Delete(crd.Name, nil)
|
||||
|
||||
exampleClient, exampleScheme, err := exampleclient.NewClient(config.GenericConfig.LoopbackClientConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("Starting a controller on instances of custom resource %q", examplecrv1.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 custom resource
|
||||
t.Logf("Creating custom resource instance")
|
||||
example := &examplecrv1.Example{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "example1",
|
||||
},
|
||||
Spec: examplecrv1.ExampleSpec{
|
||||
Foo: "hello",
|
||||
Bar: true,
|
||||
},
|
||||
Status: examplecrv1.ExampleStatus{
|
||||
State: examplecrv1.ExampleStateCreated,
|
||||
Message: "Created, not processed yet",
|
||||
},
|
||||
}
|
||||
var result examplecrv1.Example
|
||||
err = exampleClient.Post().
|
||||
Resource(examplecrv1.ExampleResourcePlural).
|
||||
Namespace(apiv1.NamespaceDefault).
|
||||
Body(example).
|
||||
Do().Into(&result)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create an instance of the custom resource: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("Waiting instance to be processed by the controller")
|
||||
if err := exampleclient.WaitForExampleInstanceProcessed(exampleClient, "example1"); err != nil {
|
||||
t.Fatalf("Instance was not processed correctly: %v", err)
|
||||
}
|
||||
t.Logf("Instance is processed")
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
# Custom Resource Example
|
||||
|
||||
**Note:** CustomResourceDefinition is the successor of the deprecated ThirdPartyResource.
|
||||
|
||||
For a client-go example using CustomResourceDefinitions, go to
|
||||
|
||||
http://github.com/kubernetes/apiextensions-apiserver/examples/client-go.
|
|
@ -8,12 +8,6 @@ load(
|
|||
"go_library",
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "third-party-resources",
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["main.go"],
|
||||
|
@ -21,12 +15,18 @@ go_library(
|
|||
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/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/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/pkg/api/v1: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,4 +1,6 @@
|
|||
# Third Party Resources Example
|
||||
# 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:
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
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",
|
||||
],
|
||||
)
|
|
@ -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"`
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
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)
|
||||
}
|
|
@ -20,7 +20,7 @@ go_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/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/pkg/api/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/pkg/apis/extensions/v1beta1:go_default_library",
|
|
@ -21,7 +21,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/rest"
|
||||
|
||||
tprv1 "k8s.io/client-go/examples/third-party-resources/apis/tpr/v1"
|
||||
tprv1 "k8s.io/client-go/examples/third-party-resources-deprecated/apis/tpr/v1"
|
||||
)
|
||||
|
||||
func NewClient(cfg *rest.Config) (*rest.RESTClient, *runtime.Scheme, error) {
|
|
@ -22,7 +22,7 @@ import (
|
|||
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"
|
||||
tprv1 "k8s.io/client-go/examples/third-party-resources-deprecated/apis/tpr/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||
"k8s.io/client-go/pkg/apis/extensions/v1beta1"
|
|
@ -14,7 +14,7 @@ go_library(
|
|||
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/examples/third-party-resources-deprecated/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",
|
|
@ -26,7 +26,7 @@ import (
|
|||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
tprv1 "k8s.io/client-go/examples/third-party-resources/apis/tpr/v1"
|
||||
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
|
|
@ -32,9 +32,9 @@ import (
|
|||
// 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"
|
||||
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() {
|
|
@ -29,9 +29,9 @@ go_test(
|
|||
"//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/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/pkg/api/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
|
|
|
@ -28,9 +28,9 @@ import (
|
|||
"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"
|
||||
exampletprv1 "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 TestClientGoThirdPartyResourceExample(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue