Skip to content

Commit 76addbe

Browse files
committed
Add set-gcp-location function.
1 parent 5378158 commit 76addbe

File tree

7 files changed

+971
-0
lines changed

7 files changed

+971
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM golang:1.17-alpine3.13
2+
ENV CGO_ENABLED=0
3+
WORKDIR /go/src/
4+
5+
COPY go.mod go.sum ./
6+
RUN go mod download
7+
8+
COPY . .
9+
RUN go build -o /usr/local/bin/function ./
10+
11+
#############################################
12+
13+
FROM alpine:3.13
14+
COPY --from=0 /usr/local/bin/function /usr/local/bin/function
15+
ENTRYPOINT ["function"]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package fieldspec
2+
3+
const (
4+
RegionFieldSpecs = `
5+
region:
6+
- path: spec/location
7+
group: storage.cnrm.cloud.google.com
8+
version: v1beta1
9+
kind: StorageBucket
10+
create: true
11+
12+
`
13+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package fieldspec
2+
3+
const (
4+
ZoneFieldSpecs = `
5+
zone:
6+
- path: spec/location
7+
apiVersion: yuwen.cnrm.cloud.google.com/v1beta1
8+
kind: Yuwen
9+
create: false
10+
`
11+
)

functions/go/gcp-set-location/go.mod

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module github.com/GoogleContainerTools/kpt-functions-catalog/functions/go/gcp-set-location
2+
3+
go 1.17
4+
5+
require (
6+
sigs.k8s.io/kustomize/api v0.10.2-0.20211202184144-fe551be87b8d
7+
sigs.k8s.io/kustomize/kyaml v0.13.1-0.20211202184144-fe551be87b8d
8+
)
9+
10+
require (
11+
github.com/PuerkitoBio/purell v1.1.1 // indirect
12+
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
13+
github.com/davecgh/go-spew v1.1.1 // indirect
14+
github.com/go-errors/errors v1.0.1 // indirect
15+
github.com/go-openapi/jsonpointer v0.19.3 // indirect
16+
github.com/go-openapi/jsonreference v0.19.3 // indirect
17+
github.com/go-openapi/swag v0.19.5 // indirect
18+
github.com/inconshreveable/mousetrap v1.0.0 // indirect
19+
github.com/mailru/easyjson v0.7.0 // indirect
20+
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
21+
github.com/pkg/errors v0.9.1 // indirect
22+
github.com/pmezard/go-difflib v1.0.0 // indirect
23+
github.com/spf13/cobra v1.2.1 // indirect
24+
github.com/spf13/pflag v1.0.5 // indirect
25+
github.com/stretchr/testify v1.7.0 // indirect
26+
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
27+
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
28+
golang.org/x/text v0.3.5 // indirect
29+
gopkg.in/yaml.v2 v2.4.0 // indirect
30+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
31+
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect
32+
sigs.k8s.io/yaml v1.2.0 // indirect
33+
)

functions/go/gcp-set-location/go.sum

Lines changed: 722 additions & 0 deletions
Large diffs are not rendered by default.

functions/go/gcp-set-location/main.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"sigs.k8s.io/kustomize/api/hasher"
8+
"sigs.k8s.io/kustomize/api/resmap"
9+
"sigs.k8s.io/kustomize/api/resource"
10+
"sigs.k8s.io/kustomize/kyaml/fn/framework"
11+
"sigs.k8s.io/kustomize/kyaml/fn/framework/command"
12+
)
13+
14+
type Processor struct {}
15+
16+
func newResMapFactory() *resmap.Factory {
17+
resourceFactory := resource.NewFactory(&hasher.Hasher{})
18+
resourceFactory.IncludeLocalConfigs = true
19+
return resmap.NewFactory(resourceFactory)
20+
}
21+
22+
func (p *Processor) Process(resourceList *framework.ResourceList) error {
23+
err := func() error{
24+
trans := &Transformer{}
25+
err := trans.Config(resourceList.FunctionConfig)
26+
if err != nil {
27+
return err
28+
}
29+
resmapFactory := newResMapFactory()
30+
resMap, err := resmapFactory.NewResMapFromRNodeSlice(resourceList.Items)
31+
if err != nil {
32+
return fmt.Errorf("failed to convert items to resource map: %w", err)
33+
}
34+
if err := trans.Transform(resMap); err != nil {
35+
return err
36+
}
37+
resourceList.Items = resMap.ToRNodeSlice()
38+
return nil
39+
}()
40+
if err != nil {
41+
resourceList.Results = framework.Results{
42+
&framework.Result{
43+
Message: err.Error(),
44+
Severity: framework.Error,
45+
},
46+
}
47+
return resourceList.Results
48+
}
49+
return nil
50+
}
51+
52+
func main() {
53+
cmd := command.Build(&Processor{}, command.StandaloneEnabled, false)
54+
if err := cmd.Execute(); err != nil {
55+
fmt.Fprintln(os.Stderr, err)
56+
os.Exit(1)
57+
}
58+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/GoogleContainerTools/kpt-functions-catalog/functions/go/gcp-set-location/fieldspec"
7+
"sigs.k8s.io/kustomize/api/filters/fsslice"
8+
"sigs.k8s.io/kustomize/api/resmap"
9+
"sigs.k8s.io/kustomize/api/types"
10+
"sigs.k8s.io/kustomize/kyaml/kio"
11+
"sigs.k8s.io/kustomize/kyaml/yaml"
12+
)
13+
14+
const (
15+
ZoneKey = "zone"
16+
RegionKey = "region"
17+
)
18+
19+
type Transformer struct {
20+
zone string
21+
region string
22+
zoneFieldSpec types.FsSlice `json:"zone,omitempty" yaml:"zone,omitempty"`
23+
regionFieldSpec types.FsSlice `json:"region,omitempty" yaml:"region,omitempty"`
24+
}
25+
26+
func (t *Transformer) Config(fnConfigNode *yaml.RNode) error {
27+
data := fnConfigNode.GetDataMap()
28+
if data == nil {
29+
return fmt.Errorf("missing `data` field in `ConfigMap` FunctionConfig")
30+
}
31+
zone, ok := data[ZoneKey]
32+
if !ok {
33+
return fmt.Errorf("missing `.data.%s` field in `ConfigMap` FunctionConfig", ZoneKey)
34+
}
35+
t.zone = zone
36+
region, ok := data[RegionKey]
37+
if !ok {
38+
return fmt.Errorf("missing `.data.%s` field in `ConfigMap` FunctionConfig", RegionKey)
39+
}
40+
t.region = region
41+
42+
// Enumerate location field specs
43+
var rfs RegionFieldSpecs
44+
if err := yaml.Unmarshal([]byte(fieldspec.RegionFieldSpecs), &rfs); err != nil {
45+
return err
46+
}
47+
48+
t.regionFieldSpec = rfs.fieldSpecs
49+
var zfs ZoneFieldSpecs
50+
if err := yaml.Unmarshal([]byte(fieldspec.ZoneFieldSpecs), &zfs); err != nil {
51+
return err
52+
}
53+
t.zoneFieldSpec = zfs.fieldSpecs
54+
return nil
55+
}
56+
57+
func (p *Transformer) Transform(m resmap.ResMap) error {
58+
return m.ApplyFilter(LocaltionFieldSpecFilter{
59+
Zone: p.zone,
60+
Region: p.region,
61+
ZFsSlice: p.zoneFieldSpec,
62+
RFsSlice: p.regionFieldSpec,
63+
})
64+
}
65+
66+
type ZoneFieldSpecs struct {
67+
fieldSpecs []types.FieldSpec `json:"zone,omitempty" yaml:"zone,omitempty"`
68+
69+
}
70+
type RegionFieldSpecs struct {
71+
fieldSpecs []types.FieldSpec `json:"region,omitempty" yaml:"region,omitempty"`
72+
}
73+
74+
var _ kio.Filter = LocaltionFieldSpecFilter{}
75+
76+
func (f LocaltionFieldSpecFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
77+
_, err := kio.FilterAll(yaml.FilterFunc(f.filter)).Filter(nodes)
78+
return nodes, err
79+
}
80+
81+
type LocaltionFieldSpecFilter struct {
82+
Zone string
83+
Region string
84+
ZFsSlice types.FsSlice `json:"zone,omitempty" yaml:"zone,omitempty"`
85+
RFsSlice types.FsSlice `json:"region,omitempty" yaml:"region,omitempty"`
86+
}
87+
88+
func (f LocaltionFieldSpecFilter) filter(node *yaml.RNode) (*yaml.RNode, error) {
89+
zoneFilter := fsslice.Filter{
90+
FsSlice: f.ZFsSlice,
91+
SetValue: f.updateZoneFn,
92+
}
93+
regionFilter := fsslice.Filter{
94+
FsSlice: f.RFsSlice,
95+
SetValue: f.updateRegionFn,
96+
}
97+
98+
if err := node.PipeE(zoneFilter, regionFilter); err != nil {
99+
return nil, err
100+
}
101+
return node, nil
102+
}
103+
104+
func (f LocaltionFieldSpecFilter) updateZoneFn(node *yaml.RNode) error {
105+
return node.PipeE(updater{location: f.Zone})
106+
}
107+
108+
func (f LocaltionFieldSpecFilter) updateRegionFn(node *yaml.RNode) error {
109+
return node.PipeE(updater{location: f.Region})
110+
}
111+
112+
type updater struct {
113+
location string
114+
}
115+
116+
func (u updater) Filter(rn *yaml.RNode) (*yaml.RNode, error) {
117+
return rn.Pipe(yaml.FieldSetter{StringValue: u.location})
118+
}
119+

0 commit comments

Comments
 (0)