Merge "Remove document plugin subcommand"

This commit is contained in:
Zuul 2020-11-12 03:03:33 +00:00 committed by Gerrit Code Review
commit df3764b7ac
36 changed files with 190 additions and 698 deletions

View File

@ -28,7 +28,6 @@ func NewDocumentCommand(cfgFactory config.Factory) *cobra.Command {
}
documentRootCmd.AddCommand(NewPullCommand(cfgFactory))
documentRootCmd.AddCommand(NewPluginCommand())
return documentRootCmd
}

View File

@ -28,11 +28,6 @@ func TestDocument(t *testing.T) {
CmdLine: "-h",
Cmd: document.NewDocumentCommand(nil),
},
{
Name: "document-plugin-with-help",
CmdLine: "-h",
Cmd: document.NewPluginCommand(),
},
}
for _, tt := range tests {
testutil.RunTest(t, tt)

View File

@ -1,78 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package document
import (
"io/ioutil"
"github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/document/plugin"
)
const (
pluginLong = `
This command is meant to be used as a kustomize exec plugin.
The command reads the configuration file CONFIG passed as a first argument and
determines a particular plugin to execute. Additional arguments may be passed
to this command and can be used by the particular plugin.
CONFIG must be a structured kubernetes manifest (i.e. resource) and must have
'apiVersion' and 'kind' keys. If the appropriate plugin was not found, the
command returns an error.
`
pluginExample = `
# Perform a replacement on a deployment. Prior to running this command,
# the file '/tmp/replacement.yaml' should be created as follows:
---
apiVersion: airshipit.org/v1alpha1
kind: ReplacementTransformer
metadata:
name: notImportantHere
replacements:
- source:
value: nginx:newtag
target:
objref:
kind: Deployment
fieldrefs:
- spec.template.spec.containers[name=nginx-latest].image
# The replacement can then be performed. Output defaults to stdout.
airshipctl document plugin /tmp/replacement.yaml
`
)
// NewPluginCommand creates a new command which can act as kustomize
// exec plugin.
func NewPluginCommand() *cobra.Command {
pluginCmd := &cobra.Command{
Use: "plugin CONFIG [ARGS]",
Short: "Run as a kustomize exec plugin",
Long: pluginLong[1:],
Example: pluginExample,
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := ioutil.ReadFile(args[0])
if err != nil {
return err
}
return plugin.ConfigureAndRun(cfg, cmd.InOrStdin(), cmd.OutOrStdout())
},
}
return pluginCmd
}

View File

@ -1,43 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package document
import (
"fmt"
"testing"
"opendev.org/airship/airshipctl/testutil"
)
func TestPlugin(t *testing.T) {
cmdTests := []*testutil.CmdTest{
{
Name: "document-plugin-cmd-with-empty-args",
CmdLine: "",
Error: fmt.Errorf("requires at least 1 arg(s), only received 0"),
Cmd: NewPluginCommand(),
},
{
Name: "document-plugin-cmd-with-nonexistent-config",
CmdLine: "/some/random/path.yaml",
Error: fmt.Errorf("open /some/random/path.yaml: no such file or directory"),
Cmd: NewPluginCommand(),
},
}
for _, tt := range cmdTests {
testutil.RunTest(t, tt)
}
}

View File

@ -1,37 +0,0 @@
This command is meant to be used as a kustomize exec plugin.
The command reads the configuration file CONFIG passed as a first argument and
determines a particular plugin to execute. Additional arguments may be passed
to this command and can be used by the particular plugin.
CONFIG must be a structured kubernetes manifest (i.e. resource) and must have
'apiVersion' and 'kind' keys. If the appropriate plugin was not found, the
command returns an error.
Usage:
plugin CONFIG [ARGS] [flags]
Examples:
# Perform a replacement on a deployment. Prior to running this command,
# the file '/tmp/replacement.yaml' should be created as follows:
---
apiVersion: airshipit.org/v1alpha1
kind: ReplacementTransformer
metadata:
name: notImportantHere
replacements:
- source:
value: nginx:newtag
target:
objref:
kind: Deployment
fieldrefs:
- spec.template.spec.containers[name=nginx-latest].image
# The replacement can then be performed. Output defaults to stdout.
airshipctl document plugin /tmp/replacement.yaml
Flags:
-h, --help help for plugin

View File

@ -5,7 +5,6 @@ Usage:
Available Commands:
help Help about any command
plugin Run as a kustomize exec plugin
pull Pulls documents from remote git repository
Flags:

View File

@ -1,29 +0,0 @@
Error: requires at least 1 arg(s), only received 0
Usage:
plugin CONFIG [ARGS] [flags]
Examples:
# Perform a replacement on a deployment. Prior to running this command,
# the file '/tmp/replacement.yaml' should be created as follows:
---
apiVersion: airshipit.org/v1alpha1
kind: ReplacementTransformer
metadata:
name: notImportantHere
replacements:
- source:
value: nginx:newtag
target:
objref:
kind: Deployment
fieldrefs:
- spec.template.spec.containers[name=nginx-latest].image
# The replacement can then be performed. Output defaults to stdout.
airshipctl document plugin /tmp/replacement.yaml
Flags:
-h, --help help for plugin

View File

@ -1,29 +0,0 @@
Error: open /some/random/path.yaml: no such file or directory
Usage:
plugin CONFIG [ARGS] [flags]
Examples:
# Perform a replacement on a deployment. Prior to running this command,
# the file '/tmp/replacement.yaml' should be created as follows:
---
apiVersion: airshipit.org/v1alpha1
kind: ReplacementTransformer
metadata:
name: notImportantHere
replacements:
- source:
value: nginx:newtag
target:
objref:
kind: Deployment
fieldrefs:
- spec.template.spec.containers[name=nginx-latest].image
# The replacement can then be performed. Output defaults to stdout.
airshipctl document plugin /tmp/replacement.yaml
Flags:
-h, --help help for plugin

View File

@ -22,6 +22,5 @@ Manage deployment documents
### SEE ALSO
* [airshipctl](airshipctl.md) - A unified entrypoint to various airship components
* [airshipctl document plugin](airshipctl_document_plugin.md) - Run as a kustomize exec plugin
* [airshipctl document pull](airshipctl_document_pull.md) - Pulls documents from remote git repository

View File

@ -1,63 +0,0 @@
## airshipctl document plugin
Run as a kustomize exec plugin
### Synopsis
This command is meant to be used as a kustomize exec plugin.
The command reads the configuration file CONFIG passed as a first argument and
determines a particular plugin to execute. Additional arguments may be passed
to this command and can be used by the particular plugin.
CONFIG must be a structured kubernetes manifest (i.e. resource) and must have
'apiVersion' and 'kind' keys. If the appropriate plugin was not found, the
command returns an error.
```
airshipctl document plugin CONFIG [ARGS] [flags]
```
### Examples
```
# Perform a replacement on a deployment. Prior to running this command,
# the file '/tmp/replacement.yaml' should be created as follows:
---
apiVersion: airshipit.org/v1alpha1
kind: ReplacementTransformer
metadata:
name: notImportantHere
replacements:
- source:
value: nginx:newtag
target:
objref:
kind: Deployment
fieldrefs:
- spec.template.spec.containers[name=nginx-latest].image
# The replacement can then be performed. Output defaults to stdout.
airshipctl document plugin /tmp/replacement.yaml
```
### Options
```
-h, --help help for plugin
```
### Options inherited from parent commands
```
--airshipconf string Path to file for airshipctl configuration. (default "$HOME/.airship/config")
--debug enable verbose output
```
### SEE ALSO
* [airshipctl document](airshipctl_document.md) - Manage deployment documents

View File

@ -32,4 +32,4 @@ hardwareProfile:
level: "0"
sizeGibibytes: 250
numberOfPhysicalDisks: 1
rotational: False
rotational: False

View File

@ -11,3 +11,7 @@ transformers:
# TODO: these two should move up to type level in the future
- ../../../../../function/hostgenerator-m3/replacements
- ../../../../../function/hardwareprofile-example/replacements
# NOTE We can not use patchesStrategicMerge directive since Strategic Merge
# plugin has to be executed once all replacements has been done. Therefore
# we need to load Strategic Merge plugin as an external plugin
- patchesstrategicmerge.yaml

View File

@ -0,0 +1,41 @@
apiVersion: builtin
kind: PatchStrategicMergeTransformer
metadata:
name: smp
patches: |-
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: hardwareprofile-example
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: host-catalogue
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: host-generation-catalogue
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: networking
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: env-vars-catalogue
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: versions-airshipctl
$patch: delete

View File

@ -11,3 +11,7 @@ transformers:
# TODO: these two should move up to type level in the future
- ../../../../../function/hostgenerator-m3/replacements
- ../../../../../function/hardwareprofile-example/replacements
# NOTE We can not use patchesStrategicMerge directive since Strategic Merge
# plugin has to be executed once all replacements has been done. Therefore
# we need to load Strategic Merge plugin as an external plugin
- patchesstrategicmerge.yaml

View File

@ -0,0 +1,41 @@
apiVersion: builtin
kind: PatchStrategicMergeTransformer
metadata:
name: smp
patches: |-
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: hardwareprofile-example
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: host-catalogue
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: host-generation-catalogue
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: networking
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: env-vars-catalogue
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: versions-airshipctl
$patch: delete

View File

@ -3,7 +3,6 @@ apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: versions-airshipctl
files:
k8scontrol:
# Host the image in a locally served location for CI

View File

@ -9,3 +9,7 @@ resources:
transformers:
- ../../../../../function/hardwareprofile-example/replacements
- ../../../../../function/hostgenerator-m3/replacements
# NOTE We can not use patchesStrategicMerge directive since Strategic Merge
# plugin has to be executed once all replacements has been done. Therefore
# we need to load Strategic Merge plugin as an external plugin
- patchesstrategicmerge.yaml

View File

@ -0,0 +1,41 @@
apiVersion: builtin
kind: PatchStrategicMergeTransformer
metadata:
name: smp
patches: |-
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: hardwareprofile-example
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: host-catalogue
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: host-generation-catalogue
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: networking
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: env-vars-catalogue
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: versions-airshipctl
$patch: delete

View File

@ -7,3 +7,7 @@ resources:
transformers:
- ../../../../../function/hostgenerator-m3/replacements
# NOTE We can not use patchesStrategicMerge directive since Strategic Merge
# plugin has to be executed once all replacements has been done. Therefore
# we need to load Strategic Merge plugin as an external plugin
- patchesstrategicmerge.yaml

View File

@ -0,0 +1,35 @@
apiVersion: builtin
kind: PatchStrategicMergeTransformer
metadata:
name: smp
patches: |-
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: host-catalogue
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: host-generation-catalogue
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: networking
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: env-vars-catalogue
$patch: delete
---
apiVersion: airshipit.org/v1alpha1
kind: VariableCatalogue
metadata:
name: versions-airshipctl
$patch: delete

View File

@ -40,8 +40,6 @@ const (
AirshipDefaultManifest = "default"
AirshipDefaultManifestRepo = "treasuremap"
AirshipDefaultManifestRepoLocation = "https://opendev.org/airship/" + AirshipDefaultManifestRepo
AirshipPluginPath = "kustomize-plugins"
AirshipPluginPathEnv = "AIRSHIP_KUSTOMIZE_PLUGINS"
// Modules
AirshipDefaultManagementType = redfish.ClientType

View File

@ -16,10 +16,7 @@ package document
import (
"io"
"os"
"path/filepath"
"strings"
"sync"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/krusty"
@ -27,8 +24,6 @@ import (
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/util"
utilyaml "opendev.org/airship/airshipctl/pkg/util/yaml"
)
@ -62,10 +57,6 @@ type Bundle interface {
Append(Document) error
}
// A singleton for the kustomize plugin path configuration
var pluginPath string
var pluginPathLock = &sync.Mutex{}
// BundleFactoryFunc is a function that returns bundle, can be used to build bundle on demand
// instead of inplace, useful, when you don't know if bundle will be needed or not, see phase for detail
type BundleFactoryFunc func() (Bundle, error)
@ -101,8 +92,8 @@ func NewBundle(fSys FileSystem, kustomizePath string) (Bundle, error) {
LoadRestrictions: options.LoadRestrictions,
DoPrune: false, // Default
PluginConfig: &types.PluginConfig{
AbsPluginHome: PluginPath(),
PluginRestrictions: types.PluginRestrictionsNone,
BpLoadingOptions: types.BploUseStaticallyLinked,
},
}
@ -115,33 +106,6 @@ func NewBundle(fSys FileSystem, kustomizePath string) (Bundle, error) {
return bundle, err
}
// PluginPath returns the kustomize plugin path
func PluginPath() string {
if pluginPath == "" {
InitPluginPath()
}
pluginPathLock.Lock()
defer pluginPathLock.Unlock()
return pluginPath
}
// InitPluginPath sets the location to look for kustomize plugins (including airshipctl itself).
func InitPluginPath() {
pluginPathLock.Lock()
defer pluginPathLock.Unlock()
// Check if we got the path via ENVIRONMENT variable
pluginPath = os.Getenv(config.AirshipPluginPathEnv)
if pluginPath != "" {
return
}
// Otherwise, we'll try putting it in the home directory
homeDir := util.UserHomeDir()
pluginPath = filepath.Join(homeDir, config.AirshipConfigDir, config.AirshipPluginPath)
}
// GetKustomizeResourceMap returns a Kustomize Resource Map for this bundle
func (b *BundleFactory) GetKustomizeResourceMap() resmap.ResMap {
return b.ResMap

View File

@ -16,14 +16,11 @@ package document_test
import (
"bytes"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/testutil"
)
@ -270,23 +267,3 @@ func TestSelectBundle(t *testing.T) {
assert.Len(t, docs, tt.expectedDocs)
}
}
func TestPluginPath(t *testing.T) {
testDir, cleanup := testutil.TempDir(t, "test-home")
defer cleanup(t)
defer setHome(testDir)()
expectedPluginPath := filepath.Join(testDir, config.AirshipConfigDir, config.AirshipPluginPath)
document.InitPluginPath()
assert.Equal(t, expectedPluginPath, document.PluginPath())
}
// setHome sets the HOME environment variable to `path`, and returns a function
// that can be used to reset HOME to its original value
func setHome(path string) (resetHome func()) {
oldHome := os.Getenv("HOME")
os.Setenv("HOME", path)
return func() {
os.Setenv("HOME", oldHome)
}
}

View File

@ -1,32 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package plugin
import (
"fmt"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// ErrPluginNotFound is returned if a plugin was not found in the plugin
// registry
type ErrPluginNotFound struct {
//PluginID group, version and kind plugin identifier
PluginID schema.GroupVersionKind
}
func (e ErrPluginNotFound) Error() string {
return fmt.Sprintf("plugin identified by %s was not found", e.PluginID.String())
}

View File

@ -1,33 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package replacement
import (
"k8s.io/apimachinery/pkg/runtime/schema"
airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1"
"opendev.org/airship/airshipctl/pkg/document/plugin/types"
)
// RegisterPlugin registers BareMetalHost generator plugin
func RegisterPlugin(registry map[schema.GroupVersionKind]types.Factory) error {
obj := &airshipv1.ReplacementTransformer{}
gvks, _, err := airshipv1.Scheme.ObjectKinds(obj)
if err != nil {
return err
}
registry[gvks[0]] = New
return nil
}

View File

@ -17,18 +17,16 @@ package replacement
import (
"encoding/base64"
"fmt"
"io"
"regexp"
"strings"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1"
"opendev.org/airship/airshipctl/pkg/document/plugin/kyamlutils"
plugtypes "opendev.org/airship/airshipctl/pkg/document/plugin/types"
"opendev.org/airship/airshipctl/pkg/errors"
)
var (
@ -41,14 +39,14 @@ const (
secretData = "data"
)
var _ plugtypes.Plugin = &plugin{}
var _ kio.Filter = &plugin{}
type plugin struct {
*airshipv1.ReplacementTransformer
}
// New creates new instance of the plugin
func New(obj map[string]interface{}) (plugtypes.Plugin, error) {
func New(obj map[string]interface{}) (kio.Filter, error) {
cfg := &airshipv1.ReplacementTransformer{}
err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj, cfg)
if err != nil {
@ -69,10 +67,6 @@ func New(obj map[string]interface{}) (plugtypes.Plugin, error) {
return p, nil
}
func (p *plugin) Run(in io.Reader, out io.Writer) error {
return errors.ErrNotImplemented{What: "ReplacementTransformer method Run is deprecated and will be removed"}
}
func (p *plugin) Filter(items []*yaml.RNode) ([]*yaml.RNode, error) {
for _, r := range p.Replacements {
val, err := getValue(items, r.Source)

View File

@ -1,66 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package plugin
import (
"io"
"sigs.k8s.io/yaml"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"opendev.org/airship/airshipctl/pkg/document/plugin/replacement"
"opendev.org/airship/airshipctl/pkg/document/plugin/templater"
"opendev.org/airship/airshipctl/pkg/document/plugin/types"
)
// DefaultPlugins returns map with plugin factories
func DefaultPlugins() (map[schema.GroupVersionKind]types.Factory, error) {
registry := make(map[schema.GroupVersionKind]types.Factory)
if err := replacement.RegisterPlugin(registry); err != nil {
return nil, err
}
if err := templater.RegisterPlugin(registry); err != nil {
return nil, err
}
return registry, nil
}
// ConfigureAndRun executes particular plugin based on group, version, kind
// which have been specified in configuration file. Config file should be
// supplied as a first element of args slice
func ConfigureAndRun(pluginCfg []byte, in io.Reader, out io.Writer) error {
rawCfg := make(map[string]interface{})
if err := yaml.Unmarshal(pluginCfg, &rawCfg); err != nil {
return err
}
uCfg := &unstructured.Unstructured{}
uCfg.SetUnstructuredContent(rawCfg)
registry, err := DefaultPlugins()
if err != nil {
return err
}
pluginFactory, ok := registry[uCfg.GroupVersionKind()]
if !ok {
return ErrPluginNotFound{PluginID: uCfg.GroupVersionKind()}
}
plugin, err := pluginFactory(rawCfg)
if err != nil {
return err
}
return plugin.Run(in, out)
}

View File

@ -1,59 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package plugin_test
import (
"io"
"testing"
"github.com/stretchr/testify/assert"
"opendev.org/airship/airshipctl/pkg/document/plugin"
)
func TestConfigureAndRun(t *testing.T) {
testCases := []struct {
pluginCfg []byte
expectedError string
in io.Reader
out io.Writer
}{
{
pluginCfg: []byte(""),
expectedError: "plugin identified by /, Kind= was not found",
},
{
pluginCfg: []byte(`---
apiVersion: airshipit.org/v1alpha1
kind: UnknownPlugin
spec:
someField: someValue`),
expectedError: "plugin identified by airshipit.org/v1alpha1, Kind=UnknownPlugin was not found",
},
{
pluginCfg: []byte(`---
apiVersion: airshipit.org/v1alpha1
kind: BareMetalGenerator
spec: -
someField: someValue`),
expectedError: "error converting YAML to JSON: yaml: line 4: block sequence entries are not allowed in this context",
},
}
for _, tc := range testCases {
err := plugin.ConfigureAndRun(tc.pluginCfg, tc.in, tc.out)
assert.EqualError(t, err, tc.expectedError)
}
}

View File

@ -1,33 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package templater
import (
"k8s.io/apimachinery/pkg/runtime/schema"
airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1"
"opendev.org/airship/airshipctl/pkg/document/plugin/types"
)
// RegisterPlugin registers BareMetalHost generator plugin
func RegisterPlugin(registry map[schema.GroupVersionKind]types.Factory) error {
obj := &airshipv1.Templater{}
gvks, _, err := airshipv1.Scheme.ObjectKinds(obj)
if err != nil {
return err
}
registry[gvks[0]] = New
return nil
}

View File

@ -17,7 +17,6 @@ package templater
import (
"bytes"
"fmt"
"io"
"text/template"
"github.com/Masterminds/sprig"
@ -27,17 +26,16 @@ import (
"sigs.k8s.io/kustomize/kyaml/yaml"
airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1"
plugtypes "opendev.org/airship/airshipctl/pkg/document/plugin/types"
)
var _ plugtypes.Plugin = &plugin{}
var _ kio.Filter = &plugin{}
type plugin struct {
*airshipv1.Templater
}
// New creates new instance of the plugin
func New(obj map[string]interface{}) (plugtypes.Plugin, error) {
func New(obj map[string]interface{}) (kio.Filter, error) {
cfg := &airshipv1.Templater{}
err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj, cfg)
if err != nil {
@ -48,21 +46,15 @@ func New(obj map[string]interface{}) (plugtypes.Plugin, error) {
}, nil
}
// Run templater plugin
func (t *plugin) Run(_ io.Reader, out io.Writer) error {
func (t *plugin) Filter(items []*yaml.RNode) ([]*yaml.RNode, error) {
out := &bytes.Buffer{}
funcMap := sprig.TxtFuncMap()
funcMap["toYaml"] = toYaml
tmpl, err := template.New("tmpl").Funcs(funcMap).Parse(t.Template)
if err != nil {
return err
return nil, err
}
return tmpl.Execute(out, t.Values)
}
func (t *plugin) Filter(items []*yaml.RNode) ([]*yaml.RNode, error) {
out := &bytes.Buffer{}
err := t.Run(nil, out)
if err != nil {
if err = tmpl.Execute(out, t.Values); err != nil {
return nil, err
}

View File

@ -1,31 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package types
import (
"io"
"sigs.k8s.io/kustomize/kyaml/kio"
)
// Plugin interface for airship document plugins
type Plugin interface {
kio.Filter
Run(io.Reader, io.Writer) error
}
// Factory function for plugins. Functions of such type are used in the plugin
// registry to instantiate a plugin object
type Factory func(map[string]interface{}) (Plugin, error)

View File

@ -1,4 +1,4 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# Licensed under the Apache License, Version 4.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
@ -14,12 +14,12 @@
shell: |
set -e
kustomize build --enable_alpha_plugins \
{{ airship_config_manifest_directory }}/{{ airship_config_site_path }}/{{ path }} |
{{ airship_config_manifest_directory }}/{{ airship_config_site_path }}/{{ path }} 2>/dev/null |
kustomize cfg grep "kind=BareMetalHost"
register: bmh_command
failed_when: "bmh_command.stdout == ''"
environment:
KUSTOMIZE_PLUGIN_HOME: "{{ ansible_env.HOME }}/.airship/kustomize-plugins"
KUSTOMIZE_PLUGIN_HOME: "/tmp"
KUSTOMIZE_ENABLE_ALPHA_COMMANDS: "true"
- set_fact:
@ -29,12 +29,12 @@
shell: |
set -e
kustomize build --enable_alpha_plugins \
{{ airship_config_manifest_directory }}/{{ airship_config_site_path }}/{{ path }} |
{{ airship_config_manifest_directory }}/{{ airship_config_site_path }}/{{ path }} 2>/dev/null |
kustomize cfg grep "metadata.name={{ item.spec.networkData.name }}"
register: netdata_command
failed_when: "netdata_command.stdout == ''"
environment:
KUSTOMIZE_PLUGIN_HOME: "{{ ansible_env.HOME }}/.airship/kustomize-plugins"
KUSTOMIZE_PLUGIN_HOME: "/tmp"
KUSTOMIZE_ENABLE_ALPHA_COMMANDS: "true"
with_items: "{{ bmh }}"

View File

@ -34,6 +34,3 @@ else
echo "Airshipctl version"
airshipctl version
fi
echo "Install airshipctl as kustomize plugins"
AIRSHIPCTL="/usr/local/bin/airshipctl" ./tools/document/build_kustomize_plugin.sh

View File

@ -1,58 +0,0 @@
#!/bin/bash
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Run this from the airshipctl project root
set -e
# This script builds a version of kustomize that is able to acces
# the ReplacementTransformer plugin.
# It assumes a build airshipctl binary in bin/, or if not,
# somewhere on the path.
if [ -f "bin/airshipctl" ]; then
AIRSHIPCTL="bin/airshipctl"
else
AIRSHIPCTL="$(which airshipctl)"
fi
: ${KUSTOMIZE_PLUGIN_HOME:="$HOME/.airship/kustomize-plugins"}
: ${AIRSHIP_TAG:="dev"}
# purge any previous airship plugins
rm -rf ${KUSTOMIZE_PLUGIN_HOME}/airshipit.org
# copy our plugin to the PLUGIN_ROOT, and give a kustomzie-friendly wrapper
for PLUGIN in ReplacementTransformer Templater; do
PLUGIN_PATH=${KUSTOMIZE_PLUGIN_HOME}/airshipit.org/v1alpha1/$(echo ${PLUGIN} | awk '{print tolower($0)}')
mkdir -p ${PLUGIN_PATH}
cat > ${PLUGIN_PATH}/${PLUGIN} <<EOF
#!/bin/bash
\$(dirname \$0)/airshipctl document plugin "\$@"
EOF
chmod +x ${PLUGIN_PATH}/${PLUGIN}
cp -p ${AIRSHIPCTL} ${PLUGIN_PATH}/
done
# make a fake "variablecatalogue" no-op plugin, so kustomize
# doesn't barf on leftover catalogues that were used to construct other transformer configs
PLUGIN_PATH=${KUSTOMIZE_PLUGIN_HOME}/airshipit.org/v1alpha1/variablecatalogue
mkdir -p ${PLUGIN_PATH}
cat > ${PLUGIN_PATH}/VariableCatalogue <<EOF
#!/bin/bash
# This is a no-op kustomize plugin
EOF
chmod +x ${PLUGIN_PATH}/VariableCatalogue
# tell the user how to use this
echo -e "The airshipctl kustomize plugin has been installed.\nRun kustomize with:"
echo -e "KUSTOMIZE_PLUGIN_HOME=$KUSTOMIZE_PLUGIN_HOME \$GOPATH/bin/kustomize build --enable_alpha_plugins ..."

View File

@ -26,7 +26,6 @@ set -xe
: ${KUBECONFIG:="${HOME}/.airship/kubeconfig"}
: ${KUBECTL:="/usr/local/bin/kubectl"}
: ${KUSTOMIZE_PLUGIN_HOME:="${HOME}/.airship/kustomize-plugins"}
TMP=$(mktemp -d)
# Use the local project airshipctl binary as the default if it exists,
@ -42,7 +41,6 @@ fi
: ${AIRSHIPCTL:="${AIRSHIPCTL_DEFAULT}"}
ACTL="${AIRSHIPCTL} --airshipconf ${AIRSHIPCONFIG} --kubeconfig ${AIRSHIPKUBECONFIG}"
export KUSTOMIZE_PLUGIN_HOME
export KUBECONFIG
# TODO: use `airshipctl config` to do this once all the needed knobs are exposed

View File

@ -29,8 +29,6 @@ TMP=$(KIND_URL=${KIND_URL} ./tools/document/get_kind.sh)
export KIND=${TMP}/kind
export KUBECTL_URL
./tools/document/build_kustomize_plugin.sh
for site_root in ${SITE_ROOTS}; do
for site in $(ls ${MANIFEST_ROOT}/${site_root}); do
echo -e "\nValidating site: ${MANIFEST_ROOT}/${site_root}/${site}\n****************"