Skip to content
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
14 changes: 14 additions & 0 deletions functions/go/gcp-set-project-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"]
38 changes: 38 additions & 0 deletions functions/go/gcp-set-project-id/consts/annotation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package consts

// annotationFieldSpecs update the KRM resources' annotations whose field spec matches the path.
// This requires the annotation to already exist in the KRM resource, which is different from kustomize's
// commonAnnotations that creates the annotation if not exist.
const AnnotationFieldSpecs = `
annotations:
- path: metadata/annotations

- path: spec/template/metadata/annotations
version: v1
kind: ReplicationController

- path: spec/template/metadata/annotations
kind: Deployment

- path: spec/template/metadata/annotations
kind: ReplicaSet

- path: spec/template/metadata/annotations
kind: DaemonSet

- path: spec/template/metadata/annotations
kind: StatefulSet

- path: spec/template/metadata/annotations
group: batch
kind: Job

- path: spec/jobTemplate/metadata/annotations
group: batch
kind: CronJob

- path: spec/jobTemplate/spec/template/metadata/annotations
group: batch
kind: CronJob

`
96 changes: 96 additions & 0 deletions functions/go/gcp-set-project-id/consts/project.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package consts

// ProjectFieldSpecs contains the fieldSpec paths of Google Cloud ProjectID
const ProjectFieldSpecs = `
projectFieldSpec:
# Blueprint redis-bucket
- path: spec/authorizedNetworkRef/external
regexPattern: (?P<prefix>projects\/)(?P<projectID>\S+)(?P<suffix>\/global\/networks\/default)
group: redis.cnrm.cloud.google.com
version: v1beta1
kind: RedisInstance

# Blueprint cluster
- path: spec/resourceRef/external
group: iam.cnrm.cloud.google.com
version: v1beta1
kind: IAMPolicyMember

# Blueprint cluster
- path: spec/projectRef/external
group: gkehub.cnrm.cloud.google.com
version: v1beta1
kind: GKEHubFeatureMembership

- path: spec/googleServiceAccount
regexPattern: (?P<prefix>\S+@)(?P<projectID>\S+)(?P<suffix>\.iam\.gserviceaccount\.com)
group: core.cnrm.cloud.google.com
version: v1beta1
kind: ConfigConnectorContext

- path: spec/member
regexPattern: (?P<prefix>serviceAccount:\S+\.svc\.id\.goog\[cnrm-system\/cnrm-controller-manager-)(?P<projectID>\S+)(?P<suffix>\])
group: iam.cnrm.cloud.google.com
version: v1beta1
kind: IAMPolicyMember
`

/*
# Test-Only
- path: metadata/name
version: v1
group: apps
kind: Deployment
create: true
*/

/* UNSUPPORTED Project FieldSpec due to substitution/partial-setter
- path: metadata/annotations[cnrm.cloud.google.com/project-id]
group: storage.cnrm.cloud.google.com
version: v1beta1
kind: StorageBucket
create: true

- path: spec/workloadIdentityConfig/identityNamespace
regexPattern: "(\s+)\.svc\.id\.goog"
group: container.cnrm.cloud.google.com
version: v1beta1
kind: ContainerCluster
create: true
- path: spec/networkRef/external
regexPattern: "projects/(\s+)/global/networks/default""
group: container.cnrm.cloud.google.com
version: v1beta1
kind: ContainerCluster
create: true

- path: spec/bindings[]/members[]/member
regexPattern: "^serviceAccount:\s+@(\s+).iam.gserviceaccount.com"
group: iam.cnrm.cloud.google.com
version: v1beta1
kind: IAMPartialPolicy
create: true
- path: spec/authority/issuer
regexPattern: "https://container.googleapis.com/v1/projects/(\s+)/locations/\s+/clusters/\s+"
group: gkehub.cnrm.cloud.google.com
version: v1beta1
kind: GKEHubMembership
- path: spec/endpoint/gkeCluster/resourceRef/external
regexPattern: "//container.googleapis.com/projects/(\s+)/locations/\s+/clusters/\s+"
group: gkehub.cnrm.cloud.google.com
version: v1beta1
kind: GKEHubMembership
create: true
- path: spec/projectRef/external
regexPattern: "//container.googleapis.com/projects/(\s+)/locations/\s+/clusters/\s+"
group: gkehub.cnrm.cloud.google.com
version: v1beta1
kind: GKEHubFeature
create: true
- path: spec/projectRef/configmanagement/configSync/git/gcpServiceAccountRef/external
regexPattern: "\s+@(\s+).iam.gserviceaccount.com"
group: gkehub.cnrm.cloud.google.com
version: v1beta1
kind: GKEHubFeatureMembership
create: true
*/
74 changes: 74 additions & 0 deletions functions/go/gcp-set-project-id/custom/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package custom

import (
"regexp"

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

var _ kio.Filter = Filter{}

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

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{
SetValue: f.updateProjectIDFn(fs.RegexPattern),
FieldSpec: fs,
}
fns = append(fns, fn)
}
return node.Pipe(fns...)
})).Filter(nodes)
return nodes, err
}

func (f Filter) updateProjectIDFn(regexPath string) filtersutil.SetFn {
return func(node *yaml.RNode) (err error) {
if regexPath == "" {
return node.PipeE(updater{ProjectID: f.ProjectID})
}
defer func() {
// recover from regex panic.
if recover() != nil {
// err = fmt.Errorf("invalid regex pattern %v", regexPath)
}
}()
re := regexp.MustCompile(regexPath)
match := re.FindStringSubmatch(node.YNode().Value)
namedGroup := make(map[string]string)
for i, name := range re.SubexpNames() {
if i != 0 && name != "" {
namedGroup[name] = match[i]
}
}
newProjectID := ""
if prefix, ok := namedGroup["prefix"]; ok {
newProjectID = newProjectID + prefix
}
newProjectID = newProjectID + f.ProjectID
if suffix, ok := namedGroup["suffix"]; ok {
newProjectID = newProjectID + suffix
}
return node.PipeE(updater{ProjectID: newProjectID})
}
}

type updater struct {
ProjectID string
}

func (u updater) Filter(rn *yaml.RNode) (*yaml.RNode, error) {
return rn.Pipe(yaml.FieldSetter{StringValue: u.ProjectID})
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
module github.com/GoogleContainerTools/kpt-functions-catalog/functions/go/set-project-id
module github.com/GoogleContainerTools/kpt-functions-catalog/functions/go/gcp-set-project-id

go 1.17

require (
github.com/GoogleContainerTools/kpt-functions-sdk/go v0.0.0-20210810181223-632b30549de6
sigs.k8s.io/kustomize/kyaml v0.11.0
sigs.k8s.io/kustomize/api v0.11.1
sigs.k8s.io/kustomize/kyaml v0.13.3
sigs.k8s.io/yaml v1.3.0
)

require (
Expand All @@ -20,13 +21,15 @@ require (
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.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-20200324143707-d3edc9973b7e // indirect
golang.org/x/text v0.3.2 // 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
)

replace sigs.k8s.io/kustomize/api => ./thirdparty/kustomize/api
Loading