Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions functions/go/gcp-set-org-id/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM golang:1.17-alpine3.13
ENV CGO_ENABLED=0
WORKDIR /go/src/

COPY go.mod go.sum ./

COPY . .
RUN go build -o /usr/local/bin/function ./

#############################################

FROM alpine:3.13
COPY --from=0 /usr/local/bin/function /usr/local/bin/function
ENTRYPOINT ["function"]
11 changes: 11 additions & 0 deletions functions/go/gcp-set-org-id/consts/organization.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package consts

// OrgFieldSpec contains the fieldSpec paths of Google Cloud OrganizationID
const OrgFieldSpec = `
organizationsIDs:
# Blueprint iam-foundation
- path: spec/resourceRef
group: iam.cnrm.cloud.google.com
version: v1beta1
kind: IAMPolicyMember
`
33 changes: 33 additions & 0 deletions functions/go/gcp-set-org-id/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module github.com/GoogleContainerTools/kpt-functions-catalog/functions/go/gcp-set-org-id

go 1.17

require (
sigs.k8s.io/kustomize/api v0.11.1
sigs.k8s.io/kustomize/kyaml v0.13.3
)

require (
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-openapi/jsonpointer v0.19.3 // indirect
github.com/go-openapi/jsonreference v0.19.3 // indirect
github.com/go-openapi/swag v0.19.5 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/mailru/easyjson v0.7.0 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/cobra v1.2.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.7.0 // indirect
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
golang.org/x/text v0.3.5 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
)
646 changes: 646 additions & 0 deletions functions/go/gcp-set-org-id/go.sum

Large diffs are not rendered by default.

58 changes: 58 additions & 0 deletions functions/go/gcp-set-org-id/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"fmt"
"os"

"sigs.k8s.io/kustomize/api/hasher"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/kyaml/fn/framework"
"sigs.k8s.io/kustomize/kyaml/fn/framework/command"
)

type Processor struct {}

func newResMapFactory() *resmap.Factory {
resourceFactory := resource.NewFactory(&hasher.Hasher{})
resourceFactory.IncludeLocalConfigs = true
return resmap.NewFactory(resourceFactory)
}

func (p *Processor) Process(resourceList *framework.ResourceList) error {
err := func() error{
trans := &Transformer{}
err := trans.Config(resourceList.FunctionConfig)
if err != nil {
return err
}
resmapFactory := newResMapFactory()
resMap, err := resmapFactory.NewResMapFromRNodeSlice(resourceList.Items)
if err != nil {
return fmt.Errorf("failed to convert items to resource map: %w", err)
}
if err := trans.Transform(resMap); err != nil {
return err
}
resourceList.Items = resMap.ToRNodeSlice()
return nil
}()
if err != nil {
resourceList.Results = framework.Results{
&framework.Result{
Message: err.Error(),
Severity: framework.Error,
},
}
return resourceList.Results
}
return nil
}

func main() {
cmd := command.Build(&Processor{}, command.StandaloneEnabled, false)
if err := cmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
62 changes: 62 additions & 0 deletions functions/go/gcp-set-org-id/plugins/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package plugins

import (
"sigs.k8s.io/kustomize/api/filters/fieldspec"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)

const OrgKind = "Organization"

var _ kio.Filter = Filter{}

type Filter struct {
OrgID string
FsSlice []types.FieldSpec
}

// isOrg determins if the rnode in current fieldspec has "kind: Organization". Expecting the orgId to be
// spec:
// resourceRef:
// apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
// kind: Organization <-- kind has to be Organization
// external: 433637338589 <-- OrgID
func isOrg(node *yaml.RNode) bool {
for i := 0; i < len(node.YNode().Content); i += 2 {
if node.YNode().Content[i].Value == "kind" {
return node.YNode().Content[i+1].Value == OrgKind
}
}
return false
}

// setOrg updates the "external" rnode's value to OrgID.
func setOrg(node *yaml.RNode, orgID string) {
for i := 0; i < len(node.YNode().Content); i += 2 {
if node.YNode().Content[i].Value == "external" {
node.YNode().Content[i+1].SetString(orgID)
}
}
}

func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
_, err := kio.FilterAll(yaml.FilterFunc(
func(node *yaml.RNode) (*yaml.RNode, error) {
var fns []yaml.Filter
for _, fs := range f.FsSlice {
fn := fieldspec.Filter{
FieldSpec: fs,
SetValue: func(node *yaml.RNode) error {
if isOrg(node) {
setOrg(node, f.OrgID)
}
return nil
},
}
fns = append(fns, fn)
}
return node.Pipe(fns...)
})).Filter(nodes)
return nodes, err
}
43 changes: 43 additions & 0 deletions functions/go/gcp-set-org-id/transformer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package main

import (
"fmt"

"github.com/GoogleContainerTools/kpt-functions-catalog/functions/go/gcp-set-org-id/consts"
"github.com/GoogleContainerTools/kpt-functions-catalog/functions/go/gcp-set-org-id/plugins"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
)

const (
OrgIDKey = "orgID"
)

type Transformer struct {
FieldSpecs []types.FieldSpec `json:"organizationsIDs,omitempty" yaml:"organizationsIDs,omitempty"`
OrgID string
}

func (p *Transformer) Config(fnConfigNode *yaml.RNode) error {
if err := yaml.Unmarshal([]byte(consts.OrgFieldSpec), &p); err != nil {
return err
}
data := fnConfigNode.GetDataMap()
if data == nil {
return fmt.Errorf("missing `data` field in `ConfigMap` FunctionConfig")
}
orgID, ok := data[OrgIDKey]
if !ok {
return fmt.Errorf("missing `.data.%s` field in `ConfigMap` FunctionConfig", OrgIDKey)
}
p.OrgID = orgID
return nil
}

func (p *Transformer) Transform(m resmap.ResMap) error {
return m.ApplyFilter(plugins.Filter{
OrgID: p.OrgID,
FsSlice: p.FieldSpecs,
})
}