mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-10 08:20:59 +00:00
Inventory info helper functions
This commit is contained in:
83
cmd/kubectl/kubectlcobra/inventory.go
Normal file
83
cmd/kubectl/kubectlcobra/inventory.go
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright 2020 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// package kubectlcobra contains cobra commands from kubectl
|
||||
package kubectlcobra
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// Separates inventory fields. This string is allowable as a
|
||||
// ConfigMap key, but it is not allowed as a character in
|
||||
// resource name.
|
||||
const fieldSeparator = "_"
|
||||
|
||||
// Inventory organizes and stores the indentifying information
|
||||
// for an object. This struct (as a string) is stored in a
|
||||
// grouping object to keep track of sets of applied objects.
|
||||
type Inventory struct {
|
||||
Namespace string
|
||||
Name string
|
||||
GroupKind schema.GroupKind
|
||||
}
|
||||
|
||||
// createInventory returns a pointer to an Inventory struct filled
|
||||
// with the passed values. This function validates the passed fields
|
||||
// and returns an error for bad parameters.
|
||||
func createInventory(namespace string,
|
||||
name string, gk schema.GroupKind) (*Inventory, error) {
|
||||
|
||||
// Namespace can be empty, but name cannot.
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("Empty name for inventory object")
|
||||
}
|
||||
if gk.Empty() {
|
||||
return nil, fmt.Errorf("Empty GroupKind for inventory object")
|
||||
}
|
||||
|
||||
return &Inventory{
|
||||
Namespace: strings.TrimSpace(namespace),
|
||||
Name: name,
|
||||
GroupKind: gk,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// parseInventory takes a string, splits it into its five fields,
|
||||
// and returns a pointer to an Inventory struct storing the
|
||||
// five fields. Example inventory string:
|
||||
//
|
||||
// test-namespace/test-name/apps/v1/ReplicaSet
|
||||
//
|
||||
// Returns an error if unable to parse and create the Inventory
|
||||
// struct.
|
||||
func parseInventory(inv string) (*Inventory, error) {
|
||||
parts := strings.Split(inv, fieldSeparator)
|
||||
if len(parts) == 4 {
|
||||
gk := schema.GroupKind{
|
||||
Group: strings.TrimSpace(parts[2]),
|
||||
Kind: strings.TrimSpace(parts[3]),
|
||||
}
|
||||
return createInventory(parts[0], parts[1], gk)
|
||||
}
|
||||
return nil, fmt.Errorf("Unable to decode inventory: %s\n", inv)
|
||||
}
|
||||
|
||||
// Equals returns true if the Inventory structs are identical;
|
||||
// false otherwise.
|
||||
func (i *Inventory) Equals(other *Inventory) bool {
|
||||
return i.String() == other.String()
|
||||
}
|
||||
|
||||
// String create a string version of the Inventory struct.
|
||||
func (i *Inventory) String() string {
|
||||
return fmt.Sprintf("%s%s%s%s%s%s%s",
|
||||
i.Namespace, fieldSeparator,
|
||||
i.Name, fieldSeparator,
|
||||
i.GroupKind.Group, fieldSeparator,
|
||||
i.GroupKind.Kind)
|
||||
}
|
||||
218
cmd/kubectl/kubectlcobra/inventory_test.go
Normal file
218
cmd/kubectl/kubectlcobra/inventory_test.go
Normal file
@@ -0,0 +1,218 @@
|
||||
// Copyright 2020 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// package kubectlcobra contains cobra commands from kubectl
|
||||
package kubectlcobra
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
func TestCreateInventory(t *testing.T) {
|
||||
tests := []struct {
|
||||
namespace string
|
||||
name string
|
||||
gk schema.GroupKind
|
||||
expected string
|
||||
isError bool
|
||||
}{
|
||||
{
|
||||
namespace: " \n",
|
||||
name: " test-name\t",
|
||||
gk: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "ReplicaSet",
|
||||
},
|
||||
expected: "_test-name_apps_ReplicaSet",
|
||||
isError: false,
|
||||
},
|
||||
{
|
||||
namespace: "test-namespace ",
|
||||
name: " test-name\t",
|
||||
gk: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "ReplicaSet",
|
||||
},
|
||||
expected: "test-namespace_test-name_apps_ReplicaSet",
|
||||
isError: false,
|
||||
},
|
||||
// Error with empty name.
|
||||
{
|
||||
namespace: "test-namespace ",
|
||||
name: " \t",
|
||||
gk: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "ReplicaSet",
|
||||
},
|
||||
expected: "",
|
||||
isError: true,
|
||||
},
|
||||
// Error with empty GroupKind.
|
||||
{
|
||||
namespace: "test-namespace",
|
||||
name: "test-name",
|
||||
gk: schema.GroupKind{},
|
||||
expected: "",
|
||||
isError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
inv, err := createInventory(test.namespace, test.name, test.gk)
|
||||
if !test.isError {
|
||||
if err != nil {
|
||||
t.Errorf("Error creating inventory when it should have worked.")
|
||||
} else if test.expected != inv.String() {
|
||||
t.Errorf("Expected inventory (%s) != created inventory(%s)\n", test.expected, inv.String())
|
||||
}
|
||||
}
|
||||
if test.isError && err == nil {
|
||||
t.Errorf("Should have returned an error in createInventory()")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInventoryEqual(t *testing.T) {
|
||||
tests := []struct {
|
||||
inventory1 *Inventory
|
||||
inventory2 *Inventory
|
||||
isEqual bool
|
||||
}{
|
||||
// Two equal inventories without a namespace
|
||||
{
|
||||
inventory1: &Inventory{
|
||||
Name: "test-inv",
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
},
|
||||
inventory2: &Inventory{
|
||||
Name: "test-inv",
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
},
|
||||
isEqual: true,
|
||||
},
|
||||
// Two equal inventories with a namespace
|
||||
{
|
||||
inventory1: &Inventory{
|
||||
Namespace: "test-namespace",
|
||||
Name: "test-inv",
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
},
|
||||
inventory2: &Inventory{
|
||||
Namespace: "test-namespace",
|
||||
Name: "test-inv",
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
},
|
||||
isEqual: true,
|
||||
},
|
||||
// One inventory with a namespace, one without -- not equal.
|
||||
{
|
||||
inventory1: &Inventory{
|
||||
Name: "test-inv",
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
},
|
||||
inventory2: &Inventory{
|
||||
Namespace: "test-namespace",
|
||||
Name: "test-inv",
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
},
|
||||
isEqual: false,
|
||||
},
|
||||
// One inventory with a Deployment, one with a ReplicaSet -- not equal.
|
||||
{
|
||||
inventory1: &Inventory{
|
||||
Name: "test-inv",
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
},
|
||||
inventory2: &Inventory{
|
||||
Name: "test-inv",
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "ReplicaSet",
|
||||
},
|
||||
},
|
||||
isEqual: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
actual := test.inventory1.Equals(test.inventory2)
|
||||
if test.isEqual && !actual {
|
||||
t.Errorf("Expected inventories equal, but actual is not: (%s)/(%s)\n", test.inventory1, test.inventory2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseInventory(t *testing.T) {
|
||||
tests := []struct {
|
||||
invStr string
|
||||
inventory *Inventory
|
||||
isError bool
|
||||
}{
|
||||
{
|
||||
invStr: "_test-name_apps_ReplicaSet\t",
|
||||
inventory: &Inventory{
|
||||
Name: "test-name",
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "ReplicaSet",
|
||||
},
|
||||
},
|
||||
isError: false,
|
||||
},
|
||||
{
|
||||
invStr: "test-namespace_test-name_apps_Deployment",
|
||||
inventory: &Inventory{
|
||||
Namespace: "test-namespace",
|
||||
Name: "test-name",
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
},
|
||||
isError: false,
|
||||
},
|
||||
// Not enough fields -- error
|
||||
{
|
||||
invStr: "_test-name_apps",
|
||||
inventory: &Inventory{},
|
||||
isError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
actual, err := parseInventory(test.invStr)
|
||||
if !test.isError {
|
||||
if err != nil {
|
||||
t.Errorf("Error parsing inventory when it should have worked.")
|
||||
} else if !test.inventory.Equals(actual) {
|
||||
t.Errorf("Expected inventory (%s) != parsed inventory (%s)\n", test.inventory, actual)
|
||||
}
|
||||
}
|
||||
if test.isError && err == nil {
|
||||
t.Errorf("Should have returned an error in parseInventory()")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user