mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-05-06 01:07:03 +00:00
add nil check for nil clients (#191)
Signed-off-by: xuezhaojun <zxue@redhat.com>
This commit is contained in:
2
go.mod
2
go.mod
@@ -11,7 +11,7 @@ require (
|
||||
github.com/onsi/gomega v1.10.1
|
||||
github.com/openshift/api v0.0.0-20210331193751-3acddb19d360
|
||||
github.com/openshift/build-machinery-go v0.0.0-20211213093930-7e33a7eb4ce3
|
||||
github.com/openshift/library-go v0.0.0-20210406144447-d9cdfbd844ea
|
||||
github.com/openshift/library-go v0.0.0-20210407110438-80b76d711afb
|
||||
github.com/spf13/cobra v1.1.1
|
||||
github.com/spf13/pflag v1.0.5
|
||||
k8s.io/api v0.21.1
|
||||
|
||||
4
go.sum
4
go.sum
@@ -423,8 +423,8 @@ github.com/openshift/build-machinery-go v0.0.0-20210209125900-0da259a2c359/go.mo
|
||||
github.com/openshift/build-machinery-go v0.0.0-20211213093930-7e33a7eb4ce3 h1:65oBhJYHzYK5VL0gF1eiYY37lLzyLZ47b9y5Kib1nf8=
|
||||
github.com/openshift/build-machinery-go v0.0.0-20211213093930-7e33a7eb4ce3/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE=
|
||||
github.com/openshift/client-go v0.0.0-20210331195552-cf6c2669e01f/go.mod h1:hHaRJ6vp2MRd/CpuZ1oJkqnMGy5eEnoAkQmKPZKcUPI=
|
||||
github.com/openshift/library-go v0.0.0-20210406144447-d9cdfbd844ea h1:kjj4KeouZS8KsRmSYg0nYHBwPYwrEhbWW0ImsC7XGro=
|
||||
github.com/openshift/library-go v0.0.0-20210406144447-d9cdfbd844ea/go.mod h1:pnz961veImKsbn7pQcuFbcVpCQosYiC1fUOjzEDeOLU=
|
||||
github.com/openshift/library-go v0.0.0-20210407110438-80b76d711afb h1:11VU4Ppng9FtJJ5D9eTQZhZjtq0KMTfy5kmvUpVeW68=
|
||||
github.com/openshift/library-go v0.0.0-20210407110438-80b76d711afb/go.mod h1:pnz961veImKsbn7pQcuFbcVpCQosYiC1fUOjzEDeOLU=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
|
||||
@@ -194,11 +194,23 @@ func CleanUpStaticObject(
|
||||
case *rbacv1.RoleBinding:
|
||||
err = client.RbacV1().RoleBindings(t.Namespace).Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
case *apiextensionsv1.CustomResourceDefinition:
|
||||
err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
if apiExtensionClient == nil {
|
||||
err = fmt.Errorf("apiExtensionClient is nil")
|
||||
} else {
|
||||
err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
}
|
||||
case *apiextensionsv1beta1.CustomResourceDefinition:
|
||||
err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
if apiExtensionClient == nil {
|
||||
err = fmt.Errorf("apiExtensionClient is nil")
|
||||
} else {
|
||||
err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
}
|
||||
case *apiregistrationv1.APIService:
|
||||
err = apiRegistrationClient.APIServices().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
if apiRegistrationClient == nil {
|
||||
err = fmt.Errorf("apiRegistrationClient is nil")
|
||||
} else {
|
||||
err = apiRegistrationClient.APIServices().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
}
|
||||
case *admissionv1.ValidatingWebhookConfiguration:
|
||||
err = client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
case *admissionv1.MutatingWebhookConfiguration:
|
||||
@@ -337,10 +349,14 @@ func ApplyDirectly(
|
||||
result.Result, result.Changed, result.Error = ApplyMutatingWebhookConfiguration(
|
||||
client.AdmissionregistrationV1(), t)
|
||||
case *apiregistrationv1.APIService:
|
||||
t.ObjectMeta.Annotations = make(map[string]string)
|
||||
checksum := fmt.Sprintf("%x", sha256.Sum256(t.Spec.CABundle))
|
||||
t.ObjectMeta.Annotations["caBundle-checksum"] = string(checksum[:]) // to trigger the update when caBundle changed
|
||||
result.Result, result.Changed, result.Error = resourceapply.ApplyAPIService(apiRegistrationClient, recorder, t)
|
||||
if apiRegistrationClient == nil {
|
||||
result.Error = fmt.Errorf("apiRegistrationClient is nil")
|
||||
} else {
|
||||
t.ObjectMeta.Annotations = make(map[string]string)
|
||||
checksum := fmt.Sprintf("%x", sha256.Sum256(t.Spec.CABundle))
|
||||
t.ObjectMeta.Annotations["caBundle-checksum"] = string(checksum[:]) // to trigger the update when caBundle changed
|
||||
result.Result, result.Changed, result.Error = resourceapply.ApplyAPIService(apiRegistrationClient, recorder, t)
|
||||
}
|
||||
default:
|
||||
genericApplyFiles = append(genericApplyFiles, file)
|
||||
}
|
||||
@@ -348,7 +364,6 @@ func ApplyDirectly(
|
||||
ret = append(ret, result)
|
||||
}
|
||||
}
|
||||
|
||||
clientHolder := resourceapply.NewKubeClientHolder(client).WithAPIExtensionsClient(apiExtensionClient)
|
||||
applyResults := resourceapply.ApplyDirectly(
|
||||
clientHolder,
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/openshift/library-go/pkg/assets"
|
||||
"github.com/openshift/library-go/pkg/operator/events"
|
||||
"github.com/openshift/library-go/pkg/operator/events/eventstesting"
|
||||
"github.com/openshift/library-go/pkg/operator/resource/resourceapply"
|
||||
operatorhelpers "github.com/openshift/library-go/pkg/operator/v1helpers"
|
||||
admissionv1 "k8s.io/api/admissionregistration/v1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
@@ -321,10 +322,12 @@ func TestApplyMutatingWebhookConfiguration(t *testing.T) {
|
||||
|
||||
func TestApplyDirectly(t *testing.T) {
|
||||
testcase := []struct {
|
||||
name string
|
||||
applyFiles map[string]runtime.Object
|
||||
applyFileNames []string
|
||||
expectErr bool
|
||||
name string
|
||||
applyFiles map[string]runtime.Object
|
||||
applyFileNames []string
|
||||
nilapiExtensionClient bool
|
||||
nilapiRegistratonClient bool
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "Apply webhooks & apiservice & secret",
|
||||
@@ -337,6 +340,45 @@ func TestApplyDirectly(t *testing.T) {
|
||||
applyFileNames: []string{"validatingwebhooks", "mutatingwebhooks", "apiservice", "secret"},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Apply webhooks & apiservice & secret with nil apiRegistrationClient",
|
||||
applyFiles: map[string]runtime.Object{
|
||||
"validatingwebhooks": newUnstructured("admissionregistration.k8s.io/v1", "ValidatingWebhookConfiguration", "", "", map[string]interface{}{"webhooks": []interface{}{}}),
|
||||
"mutatingwebhooks": newUnstructured("admissionregistration.k8s.io/v1", "MutatingWebhookConfiguration", "", "", map[string]interface{}{"webhooks": []interface{}{}}),
|
||||
"apiservice": newUnstructured("apiregistration.k8s.io/v1", "APIService", "", "", map[string]interface{}{"spec": map[string]interface{}{"service": map[string]string{"name": "svc1", "namespace": "svc1"}}}),
|
||||
"secret": newUnstructured("v1", "Secret", "ns1", "n1", map[string]interface{}{"data": map[string]interface{}{"key1": []byte("key1")}}),
|
||||
},
|
||||
applyFileNames: []string{"validatingwebhooks", "mutatingwebhooks", "apiservice", "secret"},
|
||||
nilapiRegistratonClient: true,
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Apply generic resources with nil apiExtensionclient & nil apiRegistrationClient",
|
||||
applyFiles: map[string]runtime.Object{
|
||||
"secret": newUnstructured("v1", "Secret", "ns1", "n1", map[string]interface{}{"data": map[string]interface{}{"key1": []byte("key1")}}),
|
||||
},
|
||||
nilapiExtensionClient: true,
|
||||
nilapiRegistratonClient: true,
|
||||
applyFileNames: []string{"secret"},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Apply CRD",
|
||||
applyFiles: map[string]runtime.Object{
|
||||
"crd": newUnstructured("apiextensions.k8s.io/v1beta1", "CustomResourceDefinition", "", "", map[string]interface{}{}),
|
||||
},
|
||||
applyFileNames: []string{"crd"},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Apply CRD with nil apiExtensionClient",
|
||||
applyFiles: map[string]runtime.Object{
|
||||
"crd": newUnstructured("apiextensions.k8s.io/v1beta1", "CustomResourceDefinition", "", "", map[string]interface{}{}),
|
||||
},
|
||||
applyFileNames: []string{"crd"},
|
||||
nilapiExtensionClient: true,
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Apply unhandled object",
|
||||
applyFiles: map[string]runtime.Object{
|
||||
@@ -350,20 +392,47 @@ func TestApplyDirectly(t *testing.T) {
|
||||
for _, c := range testcase {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
fakeKubeClient := fakekube.NewSimpleClientset()
|
||||
fakeResgistrationClient := fakeapiregistration.NewSimpleClientset()
|
||||
fakeExtensionClient := fakeapiextensions.NewSimpleClientset()
|
||||
results := ApplyDirectly(
|
||||
fakeKubeClient, fakeExtensionClient, fakeResgistrationClient.ApiregistrationV1(),
|
||||
eventstesting.NewTestingEventRecorder(t),
|
||||
func(name string) ([]byte, error) {
|
||||
if c.applyFiles[name] == nil {
|
||||
return nil, fmt.Errorf("Failed to find file")
|
||||
}
|
||||
fakeResgistrationClient := fakeapiregistration.NewSimpleClientset().ApiregistrationV1()
|
||||
fakeApplyFunc := func(name string) ([]byte, error) {
|
||||
if c.applyFiles[name] == nil {
|
||||
return nil, fmt.Errorf("Failed to find file")
|
||||
}
|
||||
|
||||
return json.Marshal(c.applyFiles[name])
|
||||
}
|
||||
var results []resourceapply.ApplyResult
|
||||
switch {
|
||||
case c.nilapiExtensionClient && c.nilapiRegistratonClient:
|
||||
results = ApplyDirectly(
|
||||
fakeKubeClient, nil, nil,
|
||||
eventstesting.NewTestingEventRecorder(t),
|
||||
fakeApplyFunc,
|
||||
c.applyFileNames...,
|
||||
)
|
||||
case c.nilapiExtensionClient:
|
||||
results = ApplyDirectly(
|
||||
fakeKubeClient, nil, fakeResgistrationClient,
|
||||
eventstesting.NewTestingEventRecorder(t),
|
||||
fakeApplyFunc,
|
||||
c.applyFileNames...,
|
||||
)
|
||||
case c.nilapiRegistratonClient:
|
||||
results = ApplyDirectly(
|
||||
fakeKubeClient, fakeExtensionClient, nil,
|
||||
eventstesting.NewTestingEventRecorder(t),
|
||||
fakeApplyFunc,
|
||||
c.applyFileNames...,
|
||||
)
|
||||
default:
|
||||
results = ApplyDirectly(
|
||||
fakeKubeClient, fakeExtensionClient, fakeResgistrationClient,
|
||||
eventstesting.NewTestingEventRecorder(t),
|
||||
fakeApplyFunc,
|
||||
c.applyFileNames...,
|
||||
)
|
||||
}
|
||||
|
||||
return json.Marshal(c.applyFiles[name])
|
||||
},
|
||||
c.applyFileNames...,
|
||||
)
|
||||
aggregatedErr := []error{}
|
||||
for _, r := range results {
|
||||
if r.Error != nil {
|
||||
@@ -372,7 +441,7 @@ func TestApplyDirectly(t *testing.T) {
|
||||
}
|
||||
|
||||
if len(aggregatedErr) == 0 && c.expectErr {
|
||||
t.Errorf("Expect an apply error")
|
||||
t.Errorf("Expect an apply error: %s", c.name)
|
||||
}
|
||||
if len(aggregatedErr) != 0 && !c.expectErr {
|
||||
t.Errorf("Expect no apply error, %v", operatorhelpers.NewMultiLineAggregate(aggregatedErr))
|
||||
@@ -391,9 +460,11 @@ func TestDeleteStaticObject(t *testing.T) {
|
||||
"kind1": newUnstructured("v1", "Kind1", "ns1", "n1", map[string]interface{}{"spec": map[string]interface{}{"key1": []byte("key1")}}),
|
||||
}
|
||||
testcase := []struct {
|
||||
name string
|
||||
applyFileName string
|
||||
expectErr bool
|
||||
name string
|
||||
applyFileName string
|
||||
expectErr bool
|
||||
nilapiExtensionClient bool
|
||||
nilapiRegistrationClient bool
|
||||
}{
|
||||
{
|
||||
name: "Delete validating webhooks",
|
||||
@@ -410,6 +481,12 @@ func TestDeleteStaticObject(t *testing.T) {
|
||||
applyFileName: "apiservice",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Delete apiservice with nil apiRegistrationClient",
|
||||
applyFileName: "apiservice",
|
||||
nilapiRegistrationClient: true,
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Delete secret",
|
||||
applyFileName: "secret",
|
||||
@@ -420,6 +497,12 @@ func TestDeleteStaticObject(t *testing.T) {
|
||||
applyFileName: "crd",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Delete crd with nil apiExtensionClient",
|
||||
applyFileName: "crd",
|
||||
nilapiExtensionClient: true,
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Delete unhandled object",
|
||||
applyFileName: "kind1",
|
||||
@@ -430,20 +513,47 @@ func TestDeleteStaticObject(t *testing.T) {
|
||||
for _, c := range testcase {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
fakeKubeClient := fakekube.NewSimpleClientset()
|
||||
fakeResgistrationClient := fakeapiregistration.NewSimpleClientset()
|
||||
fakeResgistrationClient := fakeapiregistration.NewSimpleClientset().ApiregistrationV1()
|
||||
fakeExtensionClient := fakeapiextensions.NewSimpleClientset()
|
||||
err := CleanUpStaticObject(
|
||||
context.TODO(),
|
||||
fakeKubeClient, fakeExtensionClient, fakeResgistrationClient.ApiregistrationV1(),
|
||||
func(name string) ([]byte, error) {
|
||||
if applyFiles[name] == nil {
|
||||
return nil, fmt.Errorf("Failed to find file")
|
||||
}
|
||||
fakeAssetFunc := func(name string) ([]byte, error) {
|
||||
if applyFiles[name] == nil {
|
||||
return nil, fmt.Errorf("Failed to find file")
|
||||
}
|
||||
|
||||
return json.Marshal(applyFiles[name])
|
||||
},
|
||||
c.applyFileName,
|
||||
)
|
||||
return json.Marshal(applyFiles[name])
|
||||
}
|
||||
|
||||
var err error
|
||||
switch {
|
||||
case c.nilapiExtensionClient && c.nilapiRegistrationClient:
|
||||
err = CleanUpStaticObject(
|
||||
context.TODO(),
|
||||
fakeKubeClient, nil, nil,
|
||||
fakeAssetFunc,
|
||||
c.applyFileName,
|
||||
)
|
||||
case c.nilapiExtensionClient:
|
||||
err = CleanUpStaticObject(
|
||||
context.TODO(),
|
||||
fakeKubeClient, nil, fakeResgistrationClient,
|
||||
fakeAssetFunc,
|
||||
c.applyFileName,
|
||||
)
|
||||
case c.nilapiRegistrationClient:
|
||||
err = CleanUpStaticObject(
|
||||
context.TODO(),
|
||||
fakeKubeClient, fakeExtensionClient, nil,
|
||||
fakeAssetFunc,
|
||||
c.applyFileName,
|
||||
)
|
||||
default:
|
||||
err = CleanUpStaticObject(
|
||||
context.TODO(),
|
||||
fakeKubeClient, fakeExtensionClient, fakeResgistrationClient,
|
||||
fakeAssetFunc,
|
||||
c.applyFileName,
|
||||
)
|
||||
}
|
||||
|
||||
if err == nil && c.expectErr {
|
||||
t.Errorf("Expect an apply error")
|
||||
|
||||
34
vendor/github.com/openshift/library-go/pkg/config/client/transport.go
generated
vendored
34
vendor/github.com/openshift/library-go/pkg/config/client/transport.go
generated
vendored
@@ -52,14 +52,40 @@ type preferredHostRT struct {
|
||||
preferredHostFn func() string
|
||||
}
|
||||
|
||||
func (t *preferredHostRT) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
preferredHost := t.preferredHostFn()
|
||||
func (rt *preferredHostRT) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
preferredHost := rt.preferredHostFn()
|
||||
|
||||
if len(preferredHost) == 0 {
|
||||
return t.baseRT.RoundTrip(r)
|
||||
return rt.baseRT.RoundTrip(r)
|
||||
}
|
||||
|
||||
r.Host = preferredHost
|
||||
r.URL.Host = preferredHost
|
||||
return t.baseRT.RoundTrip(r)
|
||||
return rt.baseRT.RoundTrip(r)
|
||||
}
|
||||
|
||||
// CancelRequest exists to facilitate cancellation.
|
||||
//
|
||||
// In general there are at least three ways of cancelling a request by an HTTP client:
|
||||
// 1. Transport.CancelRequest (depreciated)
|
||||
// 2. Request.Cancel
|
||||
// 3. Request.Context (preferred)
|
||||
//
|
||||
// While using client-go callers can specify a timeout value that gets passed directly to an http.Client.
|
||||
// The HTTP client cancels requests to the underlying Transport as if the Request's Context ended.
|
||||
// For compatibility, the Client will also use the deprecated CancelRequest method on Transport if found.
|
||||
// New RoundTripper implementations should use the Request's Context for cancellation instead of implementing CancelRequest.
|
||||
//
|
||||
// Because this wrapper might be the first or might be actually wrapped with already existing wrappers that already implement CancelRequest we need to simply conform.
|
||||
//
|
||||
// See for more details:
|
||||
// https://github.com/kubernetes/kubernetes/blob/442a69c3bdf6fe8e525b05887e57d89db1e2f3a5/staging/src/k8s.io/client-go/transport/transport.go#L257
|
||||
// https://github.com/kubernetes/kubernetes/blob/e29c568c4a9cd45d15665345aa015e21bcff52dd/staging/src/k8s.io/client-go/rest/config.go#L328
|
||||
// https://github.com/kubernetes/kubernetes/blob/3b2746c9ea9e0fa247b01dca27634e509b385eda/staging/src/k8s.io/client-go/transport/round_trippers.go#L302
|
||||
func (rt *preferredHostRT) CancelRequest(req *http.Request) {
|
||||
type canceler interface{ CancelRequest(*http.Request) }
|
||||
|
||||
if rtCanceller, ok := rt.baseRT.(canceler); ok {
|
||||
rtCanceller.CancelRequest(req)
|
||||
}
|
||||
}
|
||||
|
||||
85
vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go
generated
vendored
85
vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go
generated
vendored
@@ -2,22 +2,25 @@ package resourceapply
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
|
||||
"github.com/openshift/library-go/pkg/operator/v1helpers"
|
||||
|
||||
"github.com/openshift/api"
|
||||
"github.com/openshift/library-go/pkg/operator/events"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
storagev1 "k8s.io/api/storage/v1"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
|
||||
"github.com/openshift/api"
|
||||
"github.com/openshift/library-go/pkg/operator/events"
|
||||
"github.com/openshift/library-go/pkg/operator/v1helpers"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -47,6 +50,7 @@ type ClientHolder struct {
|
||||
kubeClient kubernetes.Interface
|
||||
apiExtensionsClient apiextensionsclient.Interface
|
||||
kubeInformers v1helpers.KubeInformersForNamespaces
|
||||
dynamicClient dynamic.Interface
|
||||
}
|
||||
|
||||
func NewClientHolder() *ClientHolder {
|
||||
@@ -72,6 +76,11 @@ func (c *ClientHolder) WithAPIExtensionsClient(client apiextensionsclient.Interf
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ClientHolder) WithDynamicClient(client dynamic.Interface) *ClientHolder {
|
||||
c.dynamicClient = client
|
||||
return c
|
||||
}
|
||||
|
||||
// ApplyDirectly applies the given manifest files to API server.
|
||||
func ApplyDirectly(clients *ClientHolder, recorder events.Recorder, manifests AssetFunc, files ...string) []ApplyResult {
|
||||
ret := []ApplyResult{}
|
||||
@@ -84,7 +93,7 @@ func ApplyDirectly(clients *ClientHolder, recorder events.Recorder, manifests As
|
||||
ret = append(ret, result)
|
||||
continue
|
||||
}
|
||||
requiredObj, _, err := genericCodec.Decode(objBytes, nil, nil)
|
||||
requiredObj, err := decode(objBytes)
|
||||
if err != nil {
|
||||
result.Error = fmt.Errorf("cannot decode %q: %v", file, err)
|
||||
ret = append(ret, result)
|
||||
@@ -97,75 +106,95 @@ func ApplyDirectly(clients *ClientHolder, recorder events.Recorder, manifests As
|
||||
case *corev1.Namespace:
|
||||
if clients.kubeClient == nil {
|
||||
result.Error = fmt.Errorf("missing kubeClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyNamespace(clients.kubeClient.CoreV1(), recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyNamespace(clients.kubeClient.CoreV1(), recorder, t)
|
||||
case *corev1.Service:
|
||||
if clients.kubeClient == nil {
|
||||
result.Error = fmt.Errorf("missing kubeClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyService(clients.kubeClient.CoreV1(), recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyService(clients.kubeClient.CoreV1(), recorder, t)
|
||||
case *corev1.Pod:
|
||||
if clients.kubeClient == nil {
|
||||
result.Error = fmt.Errorf("missing kubeClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyPod(clients.kubeClient.CoreV1(), recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyPod(clients.kubeClient.CoreV1(), recorder, t)
|
||||
case *corev1.ServiceAccount:
|
||||
if clients.kubeClient == nil {
|
||||
result.Error = fmt.Errorf("missing kubeClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyServiceAccount(clients.kubeClient.CoreV1(), recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyServiceAccount(clients.kubeClient.CoreV1(), recorder, t)
|
||||
case *corev1.ConfigMap:
|
||||
client := clients.configMapsGetter()
|
||||
if client == nil {
|
||||
result.Error = fmt.Errorf("missing kubeClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyConfigMap(client, recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyConfigMap(client, recorder, t)
|
||||
case *corev1.Secret:
|
||||
client := clients.secretsGetter()
|
||||
if client == nil {
|
||||
result.Error = fmt.Errorf("missing kubeClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplySecret(client, recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplySecret(client, recorder, t)
|
||||
case *rbacv1.ClusterRole:
|
||||
if clients.kubeClient == nil {
|
||||
result.Error = fmt.Errorf("missing kubeClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyClusterRole(clients.kubeClient.RbacV1(), recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyClusterRole(clients.kubeClient.RbacV1(), recorder, t)
|
||||
case *rbacv1.ClusterRoleBinding:
|
||||
if clients.kubeClient == nil {
|
||||
result.Error = fmt.Errorf("missing kubeClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyClusterRoleBinding(clients.kubeClient.RbacV1(), recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyClusterRoleBinding(clients.kubeClient.RbacV1(), recorder, t)
|
||||
case *rbacv1.Role:
|
||||
if clients.kubeClient == nil {
|
||||
result.Error = fmt.Errorf("missing kubeClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyRole(clients.kubeClient.RbacV1(), recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyRole(clients.kubeClient.RbacV1(), recorder, t)
|
||||
case *rbacv1.RoleBinding:
|
||||
if clients.kubeClient == nil {
|
||||
result.Error = fmt.Errorf("missing kubeClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyRoleBinding(clients.kubeClient.RbacV1(), recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyRoleBinding(clients.kubeClient.RbacV1(), recorder, t)
|
||||
case *apiextensionsv1beta1.CustomResourceDefinition:
|
||||
if clients.apiExtensionsClient == nil {
|
||||
result.Error = fmt.Errorf("missing apiExtensionsClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyCustomResourceDefinitionV1Beta1(clients.apiExtensionsClient.ApiextensionsV1beta1(), recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyCustomResourceDefinitionV1Beta1(clients.apiExtensionsClient.ApiextensionsV1beta1(), recorder, t)
|
||||
case *apiextensionsv1.CustomResourceDefinition:
|
||||
if clients.apiExtensionsClient == nil {
|
||||
result.Error = fmt.Errorf("missing apiExtensionsClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyCustomResourceDefinitionV1(clients.apiExtensionsClient.ApiextensionsV1(), recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyCustomResourceDefinitionV1(clients.apiExtensionsClient.ApiextensionsV1(), recorder, t)
|
||||
case *storagev1.StorageClass:
|
||||
if clients.kubeClient == nil {
|
||||
result.Error = fmt.Errorf("missing kubeClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyStorageClass(clients.kubeClient.StorageV1(), recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyStorageClass(clients.kubeClient.StorageV1(), recorder, t)
|
||||
case *storagev1.CSIDriver:
|
||||
if clients.kubeClient == nil {
|
||||
result.Error = fmt.Errorf("missing kubeClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyCSIDriver(clients.kubeClient.StorageV1(), recorder, t)
|
||||
}
|
||||
case *unstructured.Unstructured:
|
||||
if clients.dynamicClient == nil {
|
||||
result.Error = fmt.Errorf("missing dynamicClient")
|
||||
} else {
|
||||
result.Result, result.Changed, result.Error = ApplyKnownUnstructured(clients.dynamicClient, recorder, t)
|
||||
}
|
||||
result.Result, result.Changed, result.Error = ApplyCSIDriver(clients.kubeClient.StorageV1(), recorder, t)
|
||||
default:
|
||||
result.Error = fmt.Errorf("unhandled type %T", requiredObj)
|
||||
}
|
||||
@@ -195,3 +224,19 @@ func (c *ClientHolder) secretsGetter() corev1client.SecretsGetter {
|
||||
}
|
||||
return v1helpers.CachedSecretGetter(c.kubeClient.CoreV1(), c.kubeInformers)
|
||||
}
|
||||
|
||||
func decode(objBytes []byte) (runtime.Object, error) {
|
||||
// Try to get a typed object first
|
||||
typedObj, _, decodeErr := genericCodec.Decode(objBytes, nil, nil)
|
||||
if decodeErr == nil {
|
||||
return typedObj, nil
|
||||
}
|
||||
|
||||
// Try unstructured, hoping to recover from "no kind XXX is registered for version YYY"
|
||||
unstructuredObj, _, err := scheme.Codecs.UniversalDecoder().Decode(objBytes, nil, &unstructured.Unstructured{})
|
||||
if err != nil {
|
||||
// Return the original error
|
||||
return nil, decodeErr
|
||||
}
|
||||
return unstructuredObj, nil
|
||||
}
|
||||
|
||||
39
vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/monitoring.go
generated
vendored
39
vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/monitoring.go
generated
vendored
@@ -2,9 +2,7 @@ package resourceapply
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/imdario/mergo"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
@@ -12,7 +10,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
|
||||
@@ -48,58 +45,44 @@ func ensureServiceMonitorSpec(required, existing *unstructured.Unstructured) (*u
|
||||
}
|
||||
|
||||
// ApplyServiceMonitor applies the Prometheus service monitor.
|
||||
func ApplyServiceMonitor(client dynamic.Interface, recorder events.Recorder, serviceMonitorBytes []byte) (bool, error) {
|
||||
monitorJSON, err := yaml.YAMLToJSON(serviceMonitorBytes)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
monitorObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, monitorJSON)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
required, ok := monitorObj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("unexpected object in %t", monitorObj)
|
||||
}
|
||||
|
||||
func ApplyServiceMonitor(client dynamic.Interface, recorder events.Recorder, required *unstructured.Unstructured) (*unstructured.Unstructured, bool, error) {
|
||||
namespace := required.GetNamespace()
|
||||
|
||||
existing, err := client.Resource(serviceMonitorGVR).Namespace(namespace).Get(context.TODO(), required.GetName(), metav1.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
_, createErr := client.Resource(serviceMonitorGVR).Namespace(namespace).Create(context.TODO(), required, metav1.CreateOptions{})
|
||||
newObj, createErr := client.Resource(serviceMonitorGVR).Namespace(namespace).Create(context.TODO(), required, metav1.CreateOptions{})
|
||||
if createErr != nil {
|
||||
recorder.Warningf("ServiceMonitorCreateFailed", "Failed to create ServiceMonitor.monitoring.coreos.com/v1: %v", createErr)
|
||||
return true, createErr
|
||||
return nil, true, createErr
|
||||
}
|
||||
recorder.Eventf("ServiceMonitorCreated", "Created ServiceMonitor.monitoring.coreos.com/v1 because it was missing")
|
||||
return true, nil
|
||||
return newObj, true, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
existingCopy := existing.DeepCopy()
|
||||
|
||||
updated, endpointsModified, err := ensureServiceMonitorSpec(required, existingCopy)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
if !endpointsModified {
|
||||
return false, nil
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
if klog.V(4).Enabled() {
|
||||
klog.Infof("ServiceMonitor %q changes: %v", namespace+"/"+required.GetName(), JSONPatchNoError(existing, existingCopy))
|
||||
}
|
||||
|
||||
if _, err = client.Resource(serviceMonitorGVR).Namespace(namespace).Update(context.TODO(), updated, metav1.UpdateOptions{}); err != nil {
|
||||
newObj, err := client.Resource(serviceMonitorGVR).Namespace(namespace).Update(context.TODO(), updated, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
recorder.Warningf("ServiceMonitorUpdateFailed", "Failed to update ServiceMonitor.monitoring.coreos.com/v1: %v", err)
|
||||
return true, err
|
||||
return nil, true, err
|
||||
}
|
||||
|
||||
recorder.Eventf("ServiceMonitorUpdated", "Updated ServiceMonitor.monitoring.coreos.com/v1 because it changed")
|
||||
return true, err
|
||||
return newObj, true, err
|
||||
}
|
||||
|
||||
21
vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/unstructured.go
generated
vendored
Normal file
21
vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/unstructured.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package resourceapply
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/openshift/library-go/pkg/operator/events"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
)
|
||||
|
||||
// ApplyKnownUnstructured applies few selected Unstructured types, where it semantic knowledge
|
||||
// to merge existing & required objects intelligently. Feel free to add more.
|
||||
func ApplyKnownUnstructured(client dynamic.Interface, recorder events.Recorder, obj *unstructured.Unstructured) (*unstructured.Unstructured, bool, error) {
|
||||
serviceMonitorGK := schema.GroupKind{Group: "monitoring.coreos.com", Kind: "ServiceMonitor"}
|
||||
if obj.GetObjectKind().GroupVersionKind().GroupKind() == serviceMonitorGK {
|
||||
return ApplyServiceMonitor(client, recorder, obj)
|
||||
}
|
||||
|
||||
return nil, false, fmt.Errorf("unsupported object type: %s", obj.GetKind())
|
||||
}
|
||||
61
vendor/github.com/openshift/library-go/pkg/operator/v1helpers/args.go
generated
vendored
Normal file
61
vendor/github.com/openshift/library-go/pkg/operator/v1helpers/args.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
package v1helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
// FlagsFromUnstructured process the unstructured arguments usually retrieved from an operator's configuration file under a specific key.
|
||||
// There are only two supported/valid types for arguments, that is []sting and/or string.
|
||||
// Passing a different type yield an error.
|
||||
//
|
||||
// Use ToFlagSlice function to get a slice of string flags.
|
||||
func FlagsFromUnstructured(unstructuredArgs map[string]interface{}) (map[string][]string, error) {
|
||||
return flagsFromUnstructured(unstructuredArgs)
|
||||
}
|
||||
|
||||
// ToFlagSlice transforms the provided arguments to a slice of string flags.
|
||||
// A flag name is taken directly from the key and the value is simply attached.
|
||||
// A flag is repeated iff it has more than one value.
|
||||
func ToFlagSlice(args map[string][]string) []string {
|
||||
var keys []string
|
||||
for key := range args {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
var flags []string
|
||||
for _, key := range keys {
|
||||
for _, token := range args[key] {
|
||||
flags = append(flags, fmt.Sprintf("--%s=%s", key, token))
|
||||
}
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
// flagsFromUnstructured process the unstructured arguments (interface{}) to a map of strings.
|
||||
// There are only two supported/valid types for arguments, that is []sting and/or string.
|
||||
// Passing a different type yield an error.
|
||||
func flagsFromUnstructured(unstructuredArgs map[string]interface{}) (map[string][]string, error) {
|
||||
ret := map[string][]string{}
|
||||
for argName, argRawValue := range unstructuredArgs {
|
||||
var argsSlice []string
|
||||
var found bool
|
||||
var err error
|
||||
|
||||
argsSlice, found, err = unstructured.NestedStringSlice(unstructuredArgs, argName)
|
||||
if !found || err != nil {
|
||||
str, found, err := unstructured.NestedString(unstructuredArgs, argName)
|
||||
if !found || err != nil {
|
||||
return nil, fmt.Errorf("unable to process an argument, incorrect value %v under %v key, expected []string or string", argRawValue, argName)
|
||||
}
|
||||
argsSlice = append(argsSlice, str)
|
||||
}
|
||||
|
||||
ret[argName] = argsSlice
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -199,7 +199,7 @@ github.com/openshift/build-machinery-go/make/targets/golang
|
||||
github.com/openshift/build-machinery-go/make/targets/openshift
|
||||
github.com/openshift/build-machinery-go/make/targets/openshift/operator
|
||||
github.com/openshift/build-machinery-go/scripts
|
||||
# github.com/openshift/library-go v0.0.0-20210406144447-d9cdfbd844ea
|
||||
# github.com/openshift/library-go v0.0.0-20210407110438-80b76d711afb
|
||||
## explicit
|
||||
github.com/openshift/library-go/pkg/assets
|
||||
github.com/openshift/library-go/pkg/authorization/hardcodedauthorizer
|
||||
|
||||
Reference in New Issue
Block a user