Skip to content

Commit

Permalink
Merge pull request #3211 from Shell32-Natsu/krm-plugin-tool
Browse files Browse the repository at this point in the history
modify pluginator to support convert builtin plugin to krm function
  • Loading branch information
monopole authored Nov 18, 2020
2 parents 47b12fa + 2ae323b commit a6833bc
Show file tree
Hide file tree
Showing 14 changed files with 864 additions and 150 deletions.
30 changes: 30 additions & 0 deletions cmd/pluginator/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.PHONY: statik test all clean generate run

FUNC_WRAPPER_SRC_DIR = funcwrappersrc
FUNC_WRAPPER_DST_DIR = funcwrapper

all: test build

statik:
go get github.com/rakyll/statik

test: generate
go test ./...

generate: statik
( \
cd internal/krmfunction; \
statik -src=$(FUNC_WRAPPER_SRC_DIR) -f -p $(FUNC_WRAPPER_DST_DIR) -include=main.go,go.mod.src \
)

build: generate
go build -o pluginator main.go

install: generate
go install .

run: generate
go run . $(ARGS)

clean:
rm -f pluginator
11 changes: 10 additions & 1 deletion cmd/pluginator/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ module sigs.k8s.io/kustomize/cmd/pluginator/v2

go 1.14

require sigs.k8s.io/kustomize/api v0.6.5
require (
github.com/rakyll/statik v0.1.7
github.com/spf13/cobra v1.0.0
github.com/stretchr/testify v1.4.0
sigs.k8s.io/kustomize/api v0.6.5
sigs.k8s.io/kustomize/kyaml v0.9.4
sigs.k8s.io/yaml v1.2.0
)

replace sigs.k8s.io/kustomize/api v0.6.5 => ../../api

replace sigs.k8s.io/kustomize/kyaml v0.9.4 => ../../kyaml
46 changes: 44 additions & 2 deletions cmd/pluginator/go.sum

Large diffs are not rendered by default.

176 changes: 176 additions & 0 deletions cmd/pluginator/internal/builtinplugin/builtinplugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package builtinplugin

import (
"bufio"
"fmt"
"os"
"path/filepath"
"strings"

"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/provenance"
)

//go:generate stringer -type=pluginType
type pluginType int

const packageForGeneratedCode = "builtins"

const (
unknown pluginType = iota
Transformer
Generator
)

// ConvertToBuiltInPlugin converts the input plugin file to
// kustomize builtin plugin and writes it to proper directory
func ConvertToBuiltInPlugin() error {
root, err := inputFileRoot()
if err != nil {
return err
}
file, err := os.Open(root + ".go")
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
err = readToPackageMain(scanner, file.Name())
if err != nil {
return err
}

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

// This particular phrasing is required.
w.write(
fmt.Sprintf(
"// Code generated by pluginator on %s; DO NOT EDIT.",
root))
w.write(
fmt.Sprintf(
"// pluginator %s\n", provenance.GetProvenance().Short()))
w.write("\n")
w.write("package " + packageForGeneratedCode)

pType := unknown

for scanner.Scan() {
l := scanner.Text()
if strings.HasPrefix(l, "//go:generate") {
continue
}
if strings.HasPrefix(l, "//noinspection") {
continue
}
if l == "var "+konfig.PluginSymbol+" plugin" {
continue
}
if strings.Contains(l, " Transform(") {
if pType != unknown {
return fmt.Errorf("unexpected Transform(")
}
pType = Transformer
} else if strings.Contains(l, " Generate(") {
if pType != unknown {
return fmt.Errorf("unexpected Generate(")
}
pType = Generator
}
w.write(l)
}
if err := scanner.Err(); err != nil {
return err
}
w.write("")
w.write("func New" + root + "Plugin() resmap." + pType.String() + "Plugin {")
w.write(" return &" + root + "Plugin{}")
w.write("}")

return nil
}

func inputFileRoot() (string, error) {
n := os.Getenv("GOFILE")
if !strings.HasSuffix(n, ".go") {
return "", fmt.Errorf("%+v, expecting .go suffix on %s", provenance.GetProvenance(), n)
}
return n[:len(n)-len(".go")], nil
}

func readToPackageMain(s *bufio.Scanner, f string) error {
gotMain := false
for !gotMain && s.Scan() {
gotMain = strings.HasPrefix(s.Text(), "package main")
}
if !gotMain {
return fmt.Errorf("%s missing package main", f)
}
return nil
}

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

func newWriter(r string) (*writer, error) {
n := makeOutputFileName(r)
f, err := os.Create(n)
if err != nil {
return nil, fmt.Errorf("unable to create `%s`; %v", n, err)
}
return &writer{root: r, f: f}, nil
}

// Assume that this command is running with a $PWD of
// $HOME/kustomize/plugin/builtin/secretGenerator
// (for example). Then we want to write to
// $HOME/kustomize/api/builtins
func makeOutputFileName(root string) string {
return filepath.Join(
"..", "..", "..", "api", packageForGeneratedCode, root+".go")
}

func (w *writer) close() {
// Do this for debugging.
// fmt.Println("Generated " + makeOutputFileName(w.root))
w.f.Close()
}

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

func (w *writer) filter(in string) string {
if ok, newer := w.replace(in, "type plugin struct"); ok {
return newer
}
if ok, newer := w.replace(in, "*plugin)"); ok {
return newer
}
return in
}

// replace 'plugin' with 'FooPlugin' in context
// sensitive manner.
func (w *writer) replace(in, target string) (bool, string) {
if !strings.Contains(in, target) {
return false, ""
}
newer := strings.Replace(
target, "plugin", w.root+"Plugin", 1)
return true, strings.Replace(in, target, newer, 1)
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions cmd/pluginator/internal/krmfunction/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package krmfunction

import (
"github.com/spf13/cobra"
)

// NewKrmFunctionCmd returns a pointer to a command
func NewKrmFunctionCmd() *cobra.Command {
var outputDir string
var inputFile string

cmd := &cobra.Command{
Use: "krm -i FILE -o DIR",
Short: "Convert the plugin to KRM function instead of builtin function",
RunE: func(cmd *cobra.Command, args []string) error {
c := NewConverter(outputDir, inputFile)
return c.Convert()
},
}

cmd.Flags().StringVarP(&outputDir, "output", "o", "",
"Path to the directory which will contain the KRM function")
cmd.Flags().StringVarP(&inputFile, "input", "i", "",
"Path to the input file")

cmd.MarkFlagRequired("output")
cmd.MarkFlagRequired("input")

return cmd
}
Loading

0 comments on commit a6833bc

Please sign in to comment.