Skip to content

Commit

Permalink
Add label and annotation selector code.
Browse files Browse the repository at this point in the history
Closes #2893
  • Loading branch information
monopole committed Nov 25, 2020
1 parent f54d904 commit 5af4a81
Show file tree
Hide file tree
Showing 19 changed files with 2,810 additions and 10 deletions.
3 changes: 0 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,6 @@ build-kustomize-api: $(builtinplugins)
generate-kustomize-api:
cd api; go generate ./...

.PHONY: clean-kustomize-api
clean-kustomize-api:

.PHONY: test-unit-kustomize-api
test-unit-kustomize-api: build-kustomize-api
cd api; go test ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.version=v444.333.222"
Expand Down
8 changes: 4 additions & 4 deletions api/internal/wrappy/wnode.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,13 @@ func (wn *WNode) MarshalJSON() ([]byte, error) {
}

// MatchesAnnotationSelector implements ifc.Kunstructured.
func (wn *WNode) MatchesAnnotationSelector(string) (bool, error) {
panic("TODO(#WNode) MatchesAnnotationSelector; implement or drop from API")
func (wn *WNode) MatchesAnnotationSelector(selector string) (bool, error) {
return wn.node.MatchesAnnotationSelector(selector)
}

// MatchesLabelSelector implements ifc.Kunstructured.
func (wn *WNode) MatchesLabelSelector(string) (bool, error) {
panic("TODO(#WNode) MatchesLabelSelector; implement or drop from API")
func (wn *WNode) MatchesLabelSelector(selector string) (bool, error) {
return wn.node.MatchesAnnotationSelector(selector)
}

// SetAnnotations implements ifc.Kunstructured.
Expand Down
12 changes: 9 additions & 3 deletions kyaml/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
MYGOBIN := $(shell go env GOPATH)/bin
export PATH := $(MYGOBIN):$(PATH)

.PHONY: generate license fix vet fmt test lint tidy
.PHONY: generate license fix vet fmt test lint tidy clean
all: generate license fix vet fmt test lint tidy

fix:
Expand All @@ -25,11 +25,17 @@ tidy:
go mod tidy

lint:
(which $(MYGOBIN)/golangci-lint || go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.19.1)
$(MYGOBIN)/golangci-lint run ./...
(which $(MYGOBIN)/golangci-lint || \
go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.19.1)
$(MYGOBIN)/golangci-lint \
--skip-dirs yaml/internal/k8sgen/pkg \
run ./...

test:
go test -cover ./...

vet:
go vet ./...

clean:
rm -rf yaml/internal/k8sgen/pkg
1 change: 1 addition & 0 deletions kyaml/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ require (
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 // indirect
gopkg.in/yaml.v2 v2.3.0
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71
k8s.io/apimachinery v0.17.0 // indirect
)
63 changes: 63 additions & 0 deletions kyaml/go.sum

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions kyaml/yaml/internal/k8sgen/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

// Package k8sgen contains code generated by copying bits of k8s.io code.
// See generator/main.go for the actual (copying) generator.

//go:generate go run generator/main.go
package k8sgen
3 changes: 3 additions & 0 deletions kyaml/yaml/internal/k8sgen/generator/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/generator

go 1.15
219 changes: 219 additions & 0 deletions kyaml/yaml/internal/k8sgen/generator/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

// This is a code copier launched via `go generate`.
//
// kustomize wants to reuse the k/k label selection code.
// But while kubectl remains in the k/k repo, and depends on kustomize,
// kustomize cannot depend on k8s.io/apimachinery code. Hence the copy.
//
// When/if kubectl is finally extracted from k/k to its own repo, it can
// depend on apimachinery code via normal imports, and so can kustomize.
// At that point, this copy (and copying mechanism) can be dropped.
//
// Until then, if a bug is found in a particular instance of apimachinery,
// just increment apiMachineryVersion below to match the fixed version,
// re-generate, and if need be (highly unlikely) adjust call points.
package main

import (
"bufio"
"bytes"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
)

const (
sigsK8sIo = "sigs.k8s.io"
apiMachineryRepo = "k8s.io/apimachinery"
apiMachineryVersion = "v0.17.0"
)

var (
filesToCopy = map[string][]string{
filepath.Join("pkg", "labels"): {
"labels.go",
"selector.go",
"zz_generated.deepcopy.go",
},
filepath.Join("pkg", "selection"): {
"operator.go",
},
filepath.Join("pkg", "util", "sets"): {
"empty.go",
"string.go",
},
filepath.Join("pkg", "util", "errors"): {
"errors.go",
},
filepath.Join("pkg", "util", "validation"): {
"validation.go",
},
filepath.Join("pkg", "util", "validation", "field"): {
"errors.go",
"path.go",
},
}
)

func main() {
c := newCopier()
c.print()
runNoOutputCommand("go", "get", c.apiMachineryModule())
for dir, files := range filesToCopy {
for _, n := range files {
if err := c.copyFile(dir, n); err != nil {
log.Fatal(err)
}
}
}
}

type copier struct {
goModCache string
topPackage string
srcDir string
pgmName string
}

func (c copier) apiMachineryModule() string {
return apiMachineryRepo + "@" + apiMachineryVersion
}

func (c copier) replacementPath() string {
return filepath.Join(c.topPackage, c.subPath())
}

func (c copier) subPath() string {
return filepath.Join("internal", c.pgmName)
}

func (c copier) print() {
fmt.Printf(" apiMachineryRepo: %s\n", apiMachineryRepo)
fmt.Printf(" replacementPath: %s\n", c.replacementPath())
fmt.Printf(" goModCache: %s\n", c.goModCache)
fmt.Printf(" topPackage: %s\n", c.topPackage)
fmt.Printf(" subPath: %s\n", c.subPath())
fmt.Printf(" srcDir: %s\n", c.srcDir)
fmt.Printf(" apiMachineryModule: %s\n", c.apiMachineryModule())
fmt.Printf(" pgmName: %s\n", c.pgmName)
fmt.Printf(" pwd: %s\n", os.Getenv("PWD"))
}

func newCopier() copier {
tmp := copier{
pgmName: os.Getenv("GOPACKAGE"),
goModCache: runGetOutputCommand("go", "env", "GOMODCACHE"),
}
goMod := runGetOutputCommand("go", "env", "GOMOD")
topPackage := filepath.Join(goMod[:len(goMod)-len("go.mod")-1], "yaml")
k := strings.Index(topPackage, sigsK8sIo)
if k < 1 {
log.Fatalf("cannot find %s in %s", sigsK8sIo, topPackage)
}
tmp.srcDir = topPackage[:k-1]
tmp.topPackage = topPackage[k:]
return tmp
}

func (c copier) copyFile(dir, name string) error {
inFile, err := os.Open(
filepath.Join(c.goModCache, c.apiMachineryModule(), dir, name))
if err != nil {
return err
}
defer inFile.Close()
scanner := bufio.NewScanner(inFile)

w, err := newWriter(dir, name)
if err != nil {
return err
}
defer w.close()

w.write(
fmt.Sprintf(
// This particular phrasing is required.
"// Code generated by %s/generator from %s; DO NOT EDIT.",
c.pgmName, c.apiMachineryModule()))
w.write(
fmt.Sprintf(
"// Copied from %s\n",
filepath.Join(c.apiMachineryModule(), dir, name)))

for scanner.Scan() {
l := scanner.Text()
// Disallow recursive generation.
if strings.HasPrefix(l, "//go:generate") {
continue
}
// Don't want it to appear double generated.
if strings.HasPrefix(l, "// Code generated") {
continue
}
// Fix self-imports.
l = strings.Replace(l, apiMachineryRepo, c.replacementPath(), 1)
// Replace klog with generic log (eschewing k8s.io entirely).
l = strings.Replace(l, "\"k8s.io/klog\"", "\"log\"", 1)
l = strings.Replace(l, "klog.V(10).Infof(", "log.Printf(", 1)
w.write(l)
}
if err := scanner.Err(); err != nil {
return err
}
w.write("")
return nil
}

type writer struct {
root string
f *os.File
}

func newWriter(toDir, name string) (*writer, error) {
if err := os.MkdirAll(toDir, 0755); err != nil {
log.Printf("unable to create directory: %s", toDir)
return nil, err
}
n := filepath.Join(toDir, name)
f, err := os.Create(n)
if err != nil {
return nil, fmt.Errorf("unable to create `%s`; %v", n, err)
}
return &writer{root: toDir, f: f}, nil
}

func (w *writer) close() {
w.f.Close()
}

func (w *writer) write(line string) {
if _, err := w.f.WriteString(line + "\n"); err != nil {
log.Printf("Trouble writing: %s", line)
log.Fatalf("Error: %s", err)
}
}

func runNoOutputCommand(n string, args ...string) {
o := runGetOutputCommand(n, args...)
if len(o) > 0 {
log.Fatalf("unexpected output: %q", o)
}
}

func runGetOutputCommand(n string, args ...string) string {
cmd := exec.Command(n, args...)
var outBuf bytes.Buffer
cmd.Stdout = &outBuf
var errBuf bytes.Buffer
cmd.Stderr = &errBuf
if err := cmd.Run(); err != nil {
fmt.Printf("err: %q\n", errBuf.String())
log.Fatal(err)
}
return strings.TrimSpace(outBuf.String())
}
Loading

0 comments on commit 5af4a81

Please sign in to comment.