forked from kubernetes-sigs/kustomize
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow importing kustomize API's without relying on
plugins
(kuberne…
…tes-sigs#5525) * Allow importing kustomize API's without relying on `plugins` Introduce `kustomize_disable_go_plugin_support` go build tag to decouple the kustomize API from the `plugins` package dependency. This is advantageous for applications embedding the kusstomize API without the need for dynamic Go plugins, mitigating an increase in binary size associated with the inclusion of the plugins dependency and the population of ELF sections like `.dynsym` and `.dynstr`. The flag provides applications with the flexibility to exclude the import, catering to scenarios where dynamic Go plugin support is unnecessary. Signed-off-by: Tiago Silva <tiago.silva@goteleport.com> * fix golint by disabling some lint checks * handle code review suggestions --------- Signed-off-by: Tiago Silva <tiago.silva@goteleport.com>
- Loading branch information
Showing
3 changed files
with
86 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright 2024 The Kubernetes Authors. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
//go:build !kustomize_disable_go_plugin_support | ||
|
||
package loader | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"plugin" | ||
"reflect" | ||
|
||
"sigs.k8s.io/kustomize/api/internal/plugins/utils" | ||
"sigs.k8s.io/kustomize/api/konfig" | ||
"sigs.k8s.io/kustomize/api/resmap" | ||
"sigs.k8s.io/kustomize/kyaml/errors" | ||
"sigs.k8s.io/kustomize/kyaml/resid" | ||
) | ||
|
||
// registry is a means to avoid trying to load the same .so file | ||
// into memory more than once, which results in an error. | ||
// Each test makes its own loader, and tries to load its own plugins, | ||
// but the loaded .so files are in shared memory, so one will get | ||
// "this plugin already loaded" errors if the registry is maintained | ||
// as a Loader instance variable. So make it a package variable. | ||
var registry = make(map[string]resmap.Configurable) //nolint:gochecknoglobals | ||
|
||
func copyPlugin(c resmap.Configurable) resmap.Configurable { | ||
indirect := reflect.Indirect(reflect.ValueOf(c)) | ||
newIndirect := reflect.New(indirect.Type()) | ||
newIndirect.Elem().Set(reflect.ValueOf(indirect.Interface())) | ||
newNamed := newIndirect.Interface() | ||
return newNamed.(resmap.Configurable) //nolint:forcetypeassert | ||
} | ||
|
||
func (l *Loader) loadGoPlugin(id resid.ResId, absPath string) (resmap.Configurable, error) { | ||
regId := relativePluginPath(id) | ||
if c, ok := registry[regId]; ok { | ||
return copyPlugin(c), nil | ||
} | ||
if !utils.FileExists(absPath) { | ||
return nil, fmt.Errorf( | ||
"expected file with Go object code at: %s", absPath) | ||
} | ||
log.Printf("Attempting plugin load from %q", absPath) | ||
p, err := plugin.Open(absPath) | ||
if err != nil { | ||
return nil, errors.WrapPrefixf(err, "plugin %s fails to load", absPath) | ||
} | ||
symbol, err := p.Lookup(konfig.PluginSymbol) | ||
if err != nil { | ||
return nil, errors.WrapPrefixf( | ||
err, "plugin %s doesn't have symbol %s", | ||
regId, konfig.PluginSymbol) | ||
} | ||
c, ok := symbol.(resmap.Configurable) | ||
if !ok { | ||
return nil, fmt.Errorf("plugin %q not configurable", regId) | ||
} | ||
registry[regId] = c | ||
return copyPlugin(c), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Copyright 2024 The Kubernetes Authors. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// The build tag "kustomize_disable_go_plugin_support" is used to deactivate the | ||
// kustomize API's dependency on the "plugins" package. This is beneficial for | ||
// applications that need to embed it but do not have requirements for dynamic | ||
// Go plugins. | ||
// Including plugins as a dependency can lead to an increase in binary size due | ||
// to the population of ELF's sections such as .dynsym and .dynstr. | ||
// By utilizing this flag, applications have the flexibility to exclude the | ||
// import if they do not require support for dynamic Go plugins. | ||
//go:build kustomize_disable_go_plugin_support | ||
|
||
package loader | ||
|
||
import ( | ||
"sigs.k8s.io/kustomize/api/resmap" | ||
"sigs.k8s.io/kustomize/kyaml/errors" | ||
"sigs.k8s.io/kustomize/kyaml/resid" | ||
) | ||
|
||
func (l *Loader) loadGoPlugin(_ resid.ResId, _ string) (resmap.Configurable, error) { | ||
return nil, errors.New("plugin load is disabled") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters