Consistently use InfoHelper to get rest client

This commit is contained in:
Mikhail Mazurskiy 2021-11-05 14:10:14 +11:00
parent 8da7837865
commit 200d6ec9c4
No known key found for this signature in database
GPG Key ID: FA7917C48932DD55
3 changed files with 35 additions and 73 deletions

View File

@ -6,9 +6,7 @@ package info
import (
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/rest"
"k8s.io/kubectl/pkg/cmd/util"
"sigs.k8s.io/cli-utils/pkg/object"
)
@ -43,7 +41,7 @@ func (ih *infoHelper) UpdateInfo(info *resource.Info) error {
}
info.Mapping = mapping
c, err := ih.getClient(gvk.GroupVersion())
c, err := ih.factory.UnstructuredClientForMapping(mapping)
if err != nil {
return err
}
@ -59,19 +57,3 @@ func (ih *infoHelper) BuildInfo(obj *unstructured.Unstructured) (*resource.Info,
err = ih.UpdateInfo(info)
return info, err
}
func (ih *infoHelper) getClient(gv schema.GroupVersion) (*rest.RESTClient, error) {
cfg, err := ih.factory.ToRESTConfig()
if err != nil {
return nil, err
}
cfg.ContentConfig = resource.UnstructuredPlusDefaultContentConfig()
cfg.GroupVersion = &gv
if len(gv.Group) == 0 {
cfg.APIPath = "/api"
} else {
cfg.APIPath = "/apis"
}
return rest.RESTClientFor(cfg)
}

View File

@ -52,7 +52,6 @@ type ClusterInventoryClient struct {
builderFunc func() *resource.Builder
mapper meta.RESTMapper
validator validation.Schema
clientFunc func(*meta.RESTMapping) (resource.RESTClient, error)
InventoryFactoryFunc InventoryFactoryFunc
invToUnstructuredFunc InventoryToUnstructuredFunc
InfoHelper info.InfoHelper
@ -79,7 +78,6 @@ func NewInventoryClient(factory cmdutil.Factory,
builderFunc: builderFunc,
mapper: mapper,
validator: validator,
clientFunc: factory.UnstructuredClientForMapping,
InventoryFactoryFunc: invFunc,
invToUnstructuredFunc: invToUnstructuredFunc,
InfoHelper: info.NewInfoHelper(mapper, factory),
@ -311,10 +309,7 @@ func (cic *ClusterInventoryClient) getClusterInventoryObjsByName(inv InventoryIn
return nil, err
}
helper, err := cic.helperFromInfo(invInfo)
if err != nil {
return nil, err
}
helper := cic.helperFromInfo(invInfo)
klog.V(4).Infof("inventory object fetch by name (namespace: %q, name: %q)", inv.Namespace(), inv.Name())
res, err := helper.Get(inv.Namespace(), inv.Name())
@ -420,7 +415,7 @@ func (cic *ClusterInventoryClient) applyInventoryObj(obj *unstructured.Unstructu
if err != nil {
return err
}
helper := resource.NewHelper(invInfo.Client, invInfo.Mapping)
helper := cic.helperFromInfo(invInfo)
klog.V(4).Infof("replacing inventory object: %s/%s", invInfo.Namespace, invInfo.Name)
var overwrite = true
replacedObj, err := helper.Replace(invInfo.Namespace, invInfo.Name, overwrite, invInfo.Object)
@ -450,10 +445,7 @@ func (cic *ClusterInventoryClient) createInventoryObj(obj *unstructured.Unstruct
if err != nil {
return err
}
helper, err := cic.helperFromInfo(invInfo)
if err != nil {
return err
}
helper := cic.helperFromInfo(invInfo)
klog.V(4).Infof("creating inventory object: %s/%s", invInfo.Namespace, invInfo.Name)
var clearResourceVersion = false
createdObj, err := helper.Create(invInfo.Namespace, clearResourceVersion, invInfo.Object)
@ -478,10 +470,7 @@ func (cic *ClusterInventoryClient) deleteInventoryObjByName(obj *unstructured.Un
if err != nil {
return err
}
helper, err := cic.helperFromInfo(invInfo)
if err != nil {
return err
}
helper := cic.helperFromInfo(invInfo)
klog.V(4).Infof("deleting inventory object: %s/%s", invInfo.Namespace, invInfo.Name)
_, err = helper.Delete(invInfo.Namespace, invInfo.Name)
return err
@ -498,10 +487,7 @@ func (cic *ClusterInventoryClient) ApplyInventoryNamespace(obj *unstructured.Uns
if err != nil {
return err
}
helper, err := cic.helperFromInfo(invInfo)
if err != nil {
return err
}
helper := cic.helperFromInfo(invInfo)
klog.V(4).Infof("applying inventory namespace: %s", invInfo.Name)
if err := util.CreateApplyAnnotation(invInfo.Object, unstructured.UnstructuredJSONScheme); err != nil {
return err
@ -524,18 +510,6 @@ func (cic *ClusterInventoryClient) toInfo(obj *unstructured.Unstructured) (*reso
// helperFromInfo returns the resource.Helper to talk to the APIServer based
// on the information from the passed "info", or an error if one occurred.
func (cic *ClusterInventoryClient) helperFromInfo(info *resource.Info) (*resource.Helper, error) {
obj, err := object.InfoToObjMeta(info)
if err != nil {
return nil, err
}
mapping, err := cic.mapper.RESTMapping(obj.GroupKind)
if err != nil {
return nil, err
}
client, err := cic.clientFunc(mapping)
if err != nil {
return nil, err
}
return resource.NewHelper(client, mapping), nil
func (cic *ClusterInventoryClient) helperFromInfo(info *resource.Info) *resource.Helper {
return resource.NewHelper(info.Client, info.Mapping)
}

View File

@ -9,6 +9,8 @@ import (
"net/http"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
@ -57,8 +59,9 @@ func TestGetClusterInventoryInfo(t *testing.T) {
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
invClient, _ := NewInventoryClient(tf,
invClient, err := NewInventoryClient(tf,
WrapInventoryObj, InvInfoToConfigMap)
require.NoError(t, err)
fakeBuilder := FakeBuilder{}
fakeBuilder.SetInventoryObjs(tc.localObjs)
invClient.builderFunc = fakeBuilder.GetBuilder()
@ -162,8 +165,9 @@ func TestMerge(t *testing.T) {
drs := common.Strategies[i]
t.Run(name, func(t *testing.T) {
// Create the local inventory object storing "tc.localObjs"
invClient, _ := NewInventoryClient(tf,
invClient, err := NewInventoryClient(tf,
WrapInventoryObj, InvInfoToConfigMap)
require.NoError(t, err)
// Create a fake builder to return "tc.clusterObjs" from
// the cluster inventory object.
fakeBuilder := FakeBuilder{}
@ -192,24 +196,22 @@ func TestCreateInventory(t *testing.T) {
tests := map[string]struct {
inv InventoryInfo
localObjs object.ObjMetadataSet
isError bool
error string
}{
"Nil local inventory object is an error": {
inv: nil,
localObjs: object.ObjMetadataSet{},
isError: true,
error: "attempting create a nil inventory object",
},
"Empty local inventory object": {
inv: localInv,
localObjs: object.ObjMetadataSet{},
isError: false,
},
"Local inventory with a single object": {
inv: localInv,
localObjs: object.ObjMetadataSet{
ignoreErrInfoToObjMeta(pod2Info),
},
isError: false,
},
"Local inventory with multiple objects": {
inv: localInv,
@ -217,7 +219,6 @@ func TestCreateInventory(t *testing.T) {
ignoreErrInfoToObjMeta(pod1Info),
ignoreErrInfoToObjMeta(pod2Info),
ignoreErrInfoToObjMeta(pod3Info)},
isError: false,
},
}
@ -248,18 +249,18 @@ func TestCreateInventory(t *testing.T) {
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
invClient, _ := NewInventoryClient(tf,
invClient, err := NewInventoryClient(tf,
WrapInventoryObj, InvInfoToConfigMap)
require.NoError(t, err)
inv := invClient.invToUnstructuredFunc(tc.inv)
if inv != nil {
inv = storeObjsInInventory(tc.inv, tc.localObjs)
}
err := invClient.createInventoryObj(inv, common.DryRunNone)
if !tc.isError && err != nil {
t.Fatalf("unexpected error received: %s", err)
}
if tc.isError && err == nil {
t.Fatalf("expected error but received none")
err = invClient.createInventoryObj(inv, common.DryRunNone)
if tc.error != "" {
assert.EqualError(t, err, tc.error)
} else {
assert.NoError(t, err)
}
})
}
@ -306,8 +307,9 @@ func TestReplace(t *testing.T) {
defer tf.Cleanup()
// Client and server dry-run do not throw errors.
invClient, _ := NewInventoryClient(tf, WrapInventoryObj, InvInfoToConfigMap)
err := invClient.Replace(copyInventory(), object.ObjMetadataSet{}, common.DryRunClient)
invClient, err := NewInventoryClient(tf, WrapInventoryObj, InvInfoToConfigMap)
require.NoError(t, err)
err = invClient.Replace(copyInventory(), object.ObjMetadataSet{}, common.DryRunClient)
if err != nil {
t.Fatalf("unexpected error received: %s", err)
}
@ -319,8 +321,9 @@ func TestReplace(t *testing.T) {
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// Create inventory client, and store the cluster objs in the inventory object.
invClient, _ := NewInventoryClient(tf,
invClient, err := NewInventoryClient(tf,
WrapInventoryObj, InvInfoToConfigMap)
require.NoError(t, err)
wrappedInv := invClient.InventoryFactoryFunc(inventoryObj)
if err := wrappedInv.Store(tc.clusterObjs); err != nil {
t.Fatalf("unexpected error storing inventory objects: %s", err)
@ -380,8 +383,9 @@ func TestGetClusterObjs(t *testing.T) {
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
invClient, _ := NewInventoryClient(tf,
invClient, err := NewInventoryClient(tf,
WrapInventoryObj, InvInfoToConfigMap)
require.NoError(t, err)
// Create fake builder returning "tc.clusterObjs" from cluster inventory.
fakeBuilder := FakeBuilder{}
fakeBuilder.SetInventoryObjs(tc.clusterObjs)
@ -460,13 +464,14 @@ func TestDeleteInventoryObj(t *testing.T) {
for i := range common.Strategies {
drs := common.Strategies[i]
t.Run(name, func(t *testing.T) {
invClient, _ := NewInventoryClient(tf,
invClient, err := NewInventoryClient(tf,
WrapInventoryObj, InvInfoToConfigMap)
require.NoError(t, err)
inv := invClient.invToUnstructuredFunc(tc.inv)
if inv != nil {
inv = storeObjsInInventory(tc.inv, tc.localObjs)
}
err := invClient.deleteInventoryObjByName(inv, drs)
err = invClient.deleteInventoryObjByName(inv, drs)
if err != nil {
t.Fatalf("unexpected error received: %s", err)
}
@ -558,8 +563,9 @@ func TestMergeInventoryObjs(t *testing.T) {
for i := range common.Strategies {
drs := common.Strategies[i]
t.Run(name, func(t *testing.T) {
invClient, _ := NewInventoryClient(tf,
invClient, err := NewInventoryClient(tf,
WrapInventoryObj, InvInfoToConfigMap)
require.NoError(t, err)
inventories := []*unstructured.Unstructured{}
for _, i := range tc.invs {
inv := storeObjsInInventory(i.inv, i.invObjs)