[plugin package]: https://golang.org/pkg/plugin
[Go modules]: https://github.com/golang/go/wiki/Modules
[ELF]: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
[tensorflow plugin]: https://www.tensorflow.org/guide/extend/op

# Go plugin Caveats

A _Go plugin_ is a compilation artifact described
by the Go [plugin package].  It is built with
special flags and cannot run on its own.
It must be loaded into a running Go program.

> A normal program written in Go might be usable
> as _exec plugin_, but is not a _Go plugin_.

Go plugins allow kustomize extensions that run
without the cost marshalling/unmarshalling all
resource data to/from a subprocess for each plugin
run.  The Go plugin API assures a certain level of
consistency to avoid confusing downstream
transformers.

Go plugins work as described in the [plugin
package], but fall short of common notions
associated with the word _plugin_.

## The skew problem

Go plugin compilation creates an [ELF] formatted
`.so` file, which by definition has no information
about the provenance of the object code.

Skew between the compilation conditions (versions
of package dependencies, `GOOS`, `GOARCH`) of the
main program ELF and the plugin ELF will cause
plugin load failure, with non-helpful error
messages.

Exec plugins also lack provenance, but won't fail
due to compilation skew.

In either case, the only sensible way to share a
plugin is as some kind of _bundle_ (a git repo
URL, a git archive file, a tar file, etc.)
containing source code, tests and associated data,
unpackable under
`$XDG_CONFIG_HOME/kustomize/plugin`.

In the case of a Go plugin, an _end user_
accepting a shared plugin _must compile both
kustomize and the plugin_.

This means a one-time run of
```
# Or whatever is appropriate at time of reading
GOPATH=${whatever} GO111MODULE=on go get sigs.k8s.io/kustomize/api
```

and then a normal development cycle using

```
go build -buildmode plugin \
    -o ${wherever}/${kind}.so ${wherever}/${kind}.go
```
with paths and the release version tag (e.g. `v3.0.0`)
adjusted as needed.

For comparison, consider what one
must do to write a [tensorflow plugin].

## Why support Go plugins?

### Safety
 
The Go plugin developer sees the same API offered
to native kustomize operations, assuring certain
semantics, invariants, checks, etc. An exec
plugin sub-process dealing with this via
stdin/stdout will have an easier time screwing
things up for downstream transformers and
consumers.

Minor point: if the plugin reads files via
the kustomize-provided file `Loader` interface, it
will be constrained by kustomize file loading
restrictions.  Of course, nothing but a code audit
prevents a Go plugin from importing the `io` package
and doing whatever it wants.

### Debugging

A Go plugin developer can debug the plugin _in
situ_, setting breakpoints inside the plugin and
elsewhere while running a plugin in feature tests.

To get the best of both worlds (shareability and safety),
a developer can write an `.go` program that functions
as an _exec plugin_, but can be processed by `go generate`
to emit a _Go plugin_ (or vice versa).

### Unit of contribution 

All the builtin generators and transformers
are themselves Go plugins.  This means that
the kustomize maintainers can promote a contributed
plugin to a builtin without needing code changes
(beyond those mandated by normal code review).

### Ecosystems grow through use

Tooling could ease Go plugin _sharing_, but this
requires some critical mass of Go plugin
_authoring_, which in turn is hampered by
confusion around sharing.  [Go modules], once they
are more widely adopted, will solve the
biggest plugin sharing difficulty: ambiguous
plugin vs host dependencies.
