Skip to content

Commit 62794d8

Browse files
committed
prototype of nested package library
1 parent 8be3f71 commit 62794d8

File tree

30 files changed

+1188
-1
lines changed

30 files changed

+1188
-1
lines changed

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@ require (
1616
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
1717
gotest.tools v2.2.0+incompatible
1818
k8s.io/api v0.18.10
19+
k8s.io/apiextensions-apiserver v0.18.10
1920
k8s.io/apimachinery v0.18.10
2021
k8s.io/cli-runtime v0.18.10
2122
k8s.io/client-go v0.18.10
2223
k8s.io/klog v1.0.0
2324
k8s.io/kubectl v0.18.10
2425
sigs.k8s.io/cli-utils v0.22.5-0.20210127192708-27cfaa675296
2526
sigs.k8s.io/kustomize/cmd/config v0.8.7-0.20201211170716-cc43a2d732d1
26-
sigs.k8s.io/kustomize/kyaml v0.10.6
27+
sigs.k8s.io/kustomize/kyaml v0.10.9
2728
)
29+
30+
replace sigs.k8s.io/cli-utils v0.22.5-0.20210127192708-27cfaa675296 => ../../sigs.k8s.io/cli-utils

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,10 @@ sigs.k8s.io/kustomize/kyaml v0.10.3 h1:ARSJUMN/c3k31DYxRfZ+vp/UepUQjg9zCwny7Oj90
697697
sigs.k8s.io/kustomize/kyaml v0.10.3/go.mod h1:RA+iCHA2wPCOfv6uG6TfXXWhYsHpgErq/AljxWKuxtg=
698698
sigs.k8s.io/kustomize/kyaml v0.10.6 h1:xUJxc/k8JoWqHUahaB8DTqY0KwEPxTbTGStvW8TOcDc=
699699
sigs.k8s.io/kustomize/kyaml v0.10.6/go.mod h1:K9yg1k/HB/6xNOf5VH3LhTo1DK9/5ykSZO5uIv+Y/1k=
700+
sigs.k8s.io/kustomize/kyaml v0.10.7 h1:r0r8UEL0bL7X56HKUmhJZ+TP+nvRNGrDHHSLO7izlcQ=
701+
sigs.k8s.io/kustomize/kyaml v0.10.7/go.mod h1:K9yg1k/HB/6xNOf5VH3LhTo1DK9/5ykSZO5uIv+Y/1k=
702+
sigs.k8s.io/kustomize/kyaml v0.10.9 h1:n3WNdvPPReRNDxW+XXd2JlyZ8EII721I21D1DBpBVBE=
703+
sigs.k8s.io/kustomize/kyaml v0.10.9/go.mod h1:K9yg1k/HB/6xNOf5VH3LhTo1DK9/5ykSZO5uIv+Y/1k=
700704
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
701705
sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
702706
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=

pkg/kptfile/kptfileutil/util.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
"github.com/GoogleContainerTools/kpt/pkg/kptfile"
2525
"sigs.k8s.io/kustomize/kyaml/errors"
26+
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
2627
"sigs.k8s.io/kustomize/kyaml/yaml"
2728
)
2829

@@ -48,6 +49,12 @@ func ReadFile(dir string) (kptfile.KptFile, error) {
4849
if err = d.Decode(&kpgfile); err != nil {
4950
return kptfile.KptFile{}, errors.Errorf("unable to parse %q: %v", kptfile.KptFileName, err)
5051
}
52+
annotations := kpgfile.Annotations
53+
if annotations == nil {
54+
annotations = make(map[string]string)
55+
}
56+
annotations[kioutil.PathAnnotation] = dir
57+
kpgfile.Annotations = annotations
5158
return kpgfile, nil
5259
}
5360

pkg/live/inventoryrg.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import (
3030
"sigs.k8s.io/kustomize/kyaml/yaml"
3131
)
3232

33+
var AllGroups []string
34+
3335
// ResourceGroupGVK is the group/version/kind of the custom
3436
// resource used to store inventory.
3537
var ResourceGroupGVK = schema.GroupVersionKind{
@@ -92,6 +94,19 @@ func (icm *InventoryResourceGroup) ID() string {
9294
return ""
9395
}
9496

97+
func (icm *InventoryResourceGroup) Match(id string) bool {
98+
invID := icm.ID()
99+
if invID == id {
100+
return true
101+
}
102+
for _, g := range AllGroups {
103+
if g == id {
104+
return true
105+
}
106+
}
107+
return false
108+
}
109+
95110
// Load is an Inventory interface function returning the set of
96111
// object metadata from the wrapped ResourceGroup, or an error.
97112
func (icm *InventoryResourceGroup) Load() ([]object.ObjMetadata, error) {
@@ -187,6 +202,116 @@ func (icm *InventoryResourceGroup) GetObject() (*unstructured.Unstructured, erro
187202
return invCopy, nil
188203
}
189204

205+
func (icm *InventoryResourceGroup) LoadSubgroups() ([]object.ObjMetadata, error) {
206+
objs := []object.ObjMetadata{}
207+
if icm.inv == nil {
208+
return objs, fmt.Errorf("inventory info is nil")
209+
}
210+
klog.V(4).Infof("loading inventory...")
211+
items, exists, err := unstructured.NestedSlice(icm.inv.Object, "spec", "subgroups")
212+
if err != nil {
213+
err := fmt.Errorf("error retrieving object metadata from inventory object")
214+
return objs, err
215+
}
216+
if !exists {
217+
klog.V(4).Infof("Inventory (spec.resources) does not exist")
218+
return objs, nil
219+
}
220+
klog.V(4).Infof("loading %d inventory items", len(items))
221+
for _, itemUncast := range items {
222+
item := itemUncast.(map[string]interface{})
223+
namespace, _, err := unstructured.NestedString(item, "namespace")
224+
if err != nil {
225+
return []object.ObjMetadata{}, err
226+
}
227+
name, _, err := unstructured.NestedString(item, "name")
228+
if err != nil {
229+
return []object.ObjMetadata{}, err
230+
}
231+
group, _, err := unstructured.NestedString(item, "group")
232+
if err != nil {
233+
return []object.ObjMetadata{}, err
234+
}
235+
kind, _, err := unstructured.NestedString(item, "kind")
236+
if err != nil {
237+
return []object.ObjMetadata{}, err
238+
}
239+
groupKind := schema.GroupKind{
240+
Group: strings.TrimSpace(group),
241+
Kind: strings.TrimSpace(kind),
242+
}
243+
klog.V(4).Infof(`creating obj metadata: "%s/%s/%s"`, namespace, name, groupKind)
244+
objMeta, err := object.CreateObjMetadata(namespace, name, groupKind)
245+
if err != nil {
246+
return []object.ObjMetadata{}, err
247+
}
248+
objs = append(objs, objMeta)
249+
}
250+
return objs, nil
251+
252+
}
253+
254+
func (icm *InventoryResourceGroup) StoreSubgroups(objMetas []object.ObjMetadata) (*unstructured.Unstructured, error){
255+
if icm.inv == nil {
256+
return nil, fmt.Errorf("inventory info is nil")
257+
}
258+
klog.V(4).Infof("getting inventory resource group")
259+
// Create a slice of Resources as empty Interface
260+
klog.V(4).Infof("Creating list of %d resources", len(objMetas))
261+
var objs []interface{}
262+
for _, objMeta := range objMetas {
263+
klog.V(4).Infof(`storing inventory obj reference: "%s/%s"`, objMeta.Namespace, objMeta.Name)
264+
objs = append(objs, map[string]interface{}{
265+
"group": objMeta.GroupKind.Group,
266+
"kind": objMeta.GroupKind.Kind,
267+
"namespace": objMeta.Namespace,
268+
"name": objMeta.Name,
269+
})
270+
}
271+
// Create the inventory object by copying the template.
272+
// Adds or clears the inventory ObjMetadata to the ResourceGroup "spec.resources" section
273+
if len(objs) == 0 {
274+
klog.V(4).Infoln("clearing inventory resources")
275+
unstructured.RemoveNestedField(icm.inv.UnstructuredContent(),
276+
"spec", "subgroups")
277+
} else {
278+
klog.V(4).Infof("storing inventory (%d) resources", len(objs))
279+
err := unstructured.SetNestedSlice(icm.inv.UnstructuredContent(),
280+
objs, "spec", "subgroups")
281+
if err != nil {
282+
return nil, err
283+
}
284+
}
285+
286+
if len(icm.objMetas) > 0 {
287+
var objs []interface{}
288+
for _, objMeta := range icm.objMetas {
289+
klog.V(4).Infof(`storing inventory obj reference: "%s/%s"`, objMeta.Namespace, objMeta.Name)
290+
objs = append(objs, map[string]interface{}{
291+
"group": objMeta.GroupKind.Group,
292+
"kind": objMeta.GroupKind.Kind,
293+
"namespace": objMeta.Namespace,
294+
"name": objMeta.Name,
295+
})
296+
}
297+
// Adds or clears the inventory ObjMetadata to the ResourceGroup "spec.resources" section
298+
if len(objs) == 0 {
299+
klog.V(4).Infoln("clearing inventory resources")
300+
unstructured.RemoveNestedField(icm.inv.UnstructuredContent(),
301+
"spec", "resources")
302+
} else {
303+
klog.V(4).Infof("storing inventory (%d) resources", len(objs))
304+
err := unstructured.SetNestedSlice(icm.inv.UnstructuredContent(),
305+
objs, "spec", "resources")
306+
if err != nil {
307+
return nil, err
308+
}
309+
}
310+
}
311+
312+
return icm.inv, nil
313+
}
314+
190315
// IsResourceGroupInventory returns true if the passed object is
191316
// a ResourceGroup inventory object; false otherwise. If an error
192317
// occurs, then false is returned and the error.

pkg/live/preprocess/process_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,7 @@ func (f *fakeInventoryClient) UpdateLabels(inv inventory.InventoryInfo, labels m
129129
f.inventory.SetLabels(labels)
130130
return nil
131131
}
132+
133+
func (f *fakeInventoryClient) ApplyInventoryObj(u *unstructured.Unstructured) error {
134+
return nil
135+
}

pkg/live/rgloader.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ var _ manifestreader.ManifestLoader = &ResourceGroupManifestLoader{}
1919
// ResourceGroup versions of some kpt live apply structures.
2020
type ResourceGroupManifestLoader struct {
2121
factory util.Factory
22+
nested bool
2223
}
2324

2425
// NewResourceGroupProvider encapsulates the passed values, and returns a pointer to an ResourceGroupProvider.
@@ -28,6 +29,13 @@ func NewResourceGroupManifestLoader(f util.Factory) *ResourceGroupManifestLoader
2829
}
2930
}
3031

32+
func NewResourceGroupManifestLoaderNested(f util.Factory) *ResourceGroupManifestLoader {
33+
return &ResourceGroupManifestLoader{
34+
factory: f,
35+
nested: true,
36+
}
37+
}
38+
3139
// Factory returns the kubectl factory.
3240
func (f *ResourceGroupManifestLoader) InventoryInfo(objs []*unstructured.Unstructured) (inventory.InventoryInfo, []*unstructured.Unstructured, error) {
3341
objs, invObj := findResourceGroupInv(objs)
@@ -79,6 +87,7 @@ func (f *ResourceGroupManifestLoader) ManifestReader(reader io.Reader, args []st
7987
Path: args[0],
8088
ReaderOptions: readerOptions,
8189
},
90+
nested: f.nested,
8291
}
8392
}
8493
return rgReader, nil

pkg/live/rgpath.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,24 @@ package live
55

66
import (
77
"fmt"
8+
"os"
9+
"path/filepath"
10+
"strings"
811

912
"github.com/GoogleContainerTools/kpt/pkg/kptfile"
1013
"github.com/GoogleContainerTools/kpt/pkg/kptfile/kptfileutil"
1114
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1215
"k8s.io/klog"
1316
"sigs.k8s.io/cli-utils/pkg/common"
1417
"sigs.k8s.io/cli-utils/pkg/manifestreader"
18+
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
1519
)
1620

1721
// ResourceGroupPathManifestReader encapsulates the default path
1822
// manifest reader.
1923
type ResourceGroupPathManifestReader struct {
2024
pathReader *manifestreader.PathManifestReader
25+
nested bool
2126
}
2227

2328
// Read reads the manifests and returns them as Info objects.
@@ -43,10 +48,33 @@ func (p *ResourceGroupPathManifestReader) Read() ([]*unstructured.Unstructured,
4348
if err == nil {
4449
klog.V(4).Infof(`from Kptfile generating ResourceGroup inventory object "%s/%s/%s"`,
4550
inv.Namespace, inv.Name, inv.InventoryID)
51+
if p.nested {
52+
annotations := invObj.GetAnnotations()
53+
if annotations == nil {
54+
annotations = make(map[string]string)
55+
}
56+
for k, v := range kf.Annotations {
57+
if k == kioutil.PathAnnotation {
58+
v = strings.TrimPrefix(v, p.pathReader.Path)
59+
}
60+
annotations[k] = v
61+
}
62+
invObj.SetAnnotations(annotations)
63+
}
4664
objs = append(objs, invObj)
4765
} else {
4866
klog.V(4).Infof("unable to generate ResourceGroup inventory: %s", err)
4967
}
68+
69+
// Read Kptfile from the subdirectories
70+
if p.nested {
71+
rgs, err := getSubDirResourceGroups(p.pathReader.Path)
72+
if err != nil {
73+
klog.V(4).Infof("unable to read the sub package level ResourceGroup: %s", err)
74+
}
75+
objs = append(objs, rgs...)
76+
}
77+
5078
return objs, nil
5179
}
5280

@@ -89,3 +117,45 @@ func ResourceGroupUnstructured(name, namespace, id string) *unstructured.Unstruc
89117
}
90118
return inventoryObj
91119
}
120+
121+
func getSubDirResourceGroups(dir string) ([]*unstructured.Unstructured, error) {
122+
objs := []*unstructured.Unstructured{}
123+
124+
err := filepath.Walk(dir,
125+
func(path string, info os.FileInfo, err error) error {
126+
if err != nil {
127+
return err
128+
}
129+
if path == dir {
130+
return nil
131+
}
132+
if !info.IsDir() {
133+
return nil
134+
}
135+
kf, err := kptfileutil.ReadFile(path)
136+
if err != nil {
137+
klog.V(4).Infof("unable to parse Kptfile for ResourceGroup inventory: %s", err)
138+
return err
139+
}
140+
inv := kf.Inventory
141+
invObj, err := generateInventoryObj(inv)
142+
if err == nil {
143+
klog.V(4).Infof(`from Kptfile generating ResourceGroup inventory object "%s/%s/%s"`,
144+
inv.Namespace, inv.Name, inv.InventoryID)
145+
annotations := invObj.GetAnnotations()
146+
if annotations == nil {
147+
annotations = make(map[string]string)
148+
}
149+
for k, v := range kf.Annotations {
150+
if k == kioutil.PathAnnotation {
151+
v = strings.TrimPrefix(strings.TrimPrefix(v, dir), string(filepath.Separator))
152+
}
153+
annotations[k] = v
154+
}
155+
invObj.SetAnnotations(annotations)
156+
objs = append(objs, invObj)
157+
}
158+
return nil
159+
})
160+
return objs, err
161+
}

0 commit comments

Comments
 (0)