Add Kustomize document filesystem layer

Add document filesystem object to avoid direct kustomize imports by
other packages in airshipctl, document.filesystem also extends
kustomize filesystem with temporary file methods.

Relates-To: #11
Closes: #11

Change-Id: Ia8034048d80d79d5996dce0e283828644fbef906
This commit is contained in:
Kostiantyn Kalynovskyi 2020-02-25 14:20:57 -06:00
parent 7f06e556a4
commit 76a280ead0
9 changed files with 34 additions and 39 deletions

View File

@ -14,8 +14,6 @@ import (
"opendev.org/airship/airshipctl/pkg/environment" "opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/pkg/log" "opendev.org/airship/airshipctl/pkg/log"
"opendev.org/airship/airshipctl/pkg/util" "opendev.org/airship/airshipctl/pkg/util"
"sigs.k8s.io/kustomize/v3/pkg/fs"
) )
const ( const (
@ -48,7 +46,7 @@ func GenerateBootstrapIso(settings *environment.AirshipCTLSettings, args []strin
// TODO (dukov) replace with the appropriate function once it's available // TODO (dukov) replace with the appropriate function once it's available
// in document module // in document module
docBundle, err := document.NewBundle(fs.MakeRealFS(), manifest.TargetPath, "") docBundle, err := document.NewBundle(document.NewDocumentFs(), manifest.TargetPath, "")
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,18 +1,15 @@
package initinfra package initinfra
import ( import (
"sigs.k8s.io/kustomize/v3/pkg/fs"
"opendev.org/airship/airshipctl/pkg/config" "opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/pkg/environment" "opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/pkg/k8s/client" "opendev.org/airship/airshipctl/pkg/k8s/client"
"opendev.org/airship/airshipctl/pkg/k8s/kubectl"
) )
// Infra is an abstraction used to initialize base infrastructure // Infra is an abstraction used to initialize base infrastructure
type Infra struct { type Infra struct {
FileSystem fs.FileSystem FileSystem document.FileSystem
RootSettings *environment.AirshipCTLSettings RootSettings *environment.AirshipCTLSettings
Client client.Interface Client client.Interface
@ -30,7 +27,7 @@ func NewInfra(rs *environment.AirshipCTLSettings) *Infra {
// Run intinfra subcommand logic // Run intinfra subcommand logic
func (infra *Infra) Run() error { func (infra *Infra) Run() error {
infra.FileSystem = kubectl.Buffer{FileSystem: fs.MakeRealFS()} infra.FileSystem = document.NewDocumentFs()
var err error var err error
infra.Client, err = client.NewClient(infra.RootSettings) infra.Client, err = client.NewClient(infra.RootSettings)
if err != nil { if err != nil {

View File

@ -9,7 +9,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"opendev.org/airship/airshipctl/pkg/cluster/initinfra" "opendev.org/airship/airshipctl/pkg/cluster/initinfra"
"opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/document"
@ -65,7 +64,7 @@ func TestDeploy(t *testing.T) {
infra.ClusterType = "ephemeral" infra.ClusterType = "ephemeral"
infra.DryRun = true infra.DryRun = true
infra.FileSystem = kubectl.Buffer{FileSystem: fs.MakeRealFS()} infra.FileSystem = document.NewDocumentFs()
kctl := kubectl.NewKubectl(tf) kctl := kubectl.NewKubectl(tf)
tc := TestClient{ tc := TestClient{

View File

@ -7,7 +7,6 @@ import (
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct" "sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer" "sigs.k8s.io/kustomize/v3/k8sdeps/transformer"
"sigs.k8s.io/kustomize/v3/k8sdeps/validator" "sigs.k8s.io/kustomize/v3/k8sdeps/validator"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/loader" "sigs.k8s.io/kustomize/v3/pkg/loader"
"sigs.k8s.io/kustomize/v3/pkg/plugins" "sigs.k8s.io/kustomize/v3/pkg/plugins"
"sigs.k8s.io/kustomize/v3/pkg/resmap" "sigs.k8s.io/kustomize/v3/pkg/resmap"
@ -37,7 +36,7 @@ type KustomizeBuildOptions struct {
type BundleFactory struct { type BundleFactory struct {
KustomizeBuildOptions KustomizeBuildOptions
resmap.ResMap resmap.ResMap
fs.FileSystem FileSystem
} }
// Bundle interface provides the specification for a bundle implementation // Bundle interface provides the specification for a bundle implementation
@ -47,8 +46,8 @@ type Bundle interface {
SetKustomizeResourceMap(resmap.ResMap) error SetKustomizeResourceMap(resmap.ResMap) error
GetKustomizeBuildOptions() KustomizeBuildOptions GetKustomizeBuildOptions() KustomizeBuildOptions
SetKustomizeBuildOptions(KustomizeBuildOptions) error SetKustomizeBuildOptions(KustomizeBuildOptions) error
SetFileSystem(fs.FileSystem) error SetFileSystem(FileSystem) error
GetFileSystem() fs.FileSystem GetFileSystem() FileSystem
Select(selector Selector) ([]Document, error) Select(selector Selector) ([]Document, error)
GetByGvk(string, string, string) ([]Document, error) GetByGvk(string, string, string) ([]Document, error)
GetByName(string) (Document, error) GetByName(string) (Document, error)
@ -60,7 +59,7 @@ type Bundle interface {
// NewBundle is a convenience function to create a new bundle // NewBundle is a convenience function to create a new bundle
// Over time, it will evolve to support allowing more control // Over time, it will evolve to support allowing more control
// for kustomize plugins // for kustomize plugins
func NewBundle(fSys fs.FileSystem, kustomizePath string, outputPath string) (bundle Bundle, err error) { func NewBundle(fSys FileSystem, kustomizePath string, outputPath string) (bundle Bundle, err error) {
var options = KustomizeBuildOptions{ var options = KustomizeBuildOptions{
KustomizationPath: kustomizePath, KustomizationPath: kustomizePath,
OutputPath: outputPath, OutputPath: outputPath,
@ -141,13 +140,13 @@ func (b *BundleFactory) SetKustomizeBuildOptions(k KustomizeBuildOptions) error
} }
// SetFileSystem sets the filesystem that will be used by this bundle // SetFileSystem sets the filesystem that will be used by this bundle
func (b *BundleFactory) SetFileSystem(fSys fs.FileSystem) error { func (b *BundleFactory) SetFileSystem(fSys FileSystem) error {
b.FileSystem = fSys b.FileSystem = fSys
return nil return nil
} }
// GetFileSystem gets the filesystem that will be used by this bundle // GetFileSystem gets the filesystem that will be used by this bundle
func (b *BundleFactory) GetFileSystem() fs.FileSystem { func (b *BundleFactory) GetFileSystem() FileSystem {
return b.FileSystem return b.FileSystem
} }

View File

@ -1,4 +1,4 @@
package kubectl package document
import ( import (
"io/ioutil" "io/ioutil"
@ -18,12 +18,17 @@ type FileSystem interface {
TempFile(string, string) (File, error) TempFile(string, string) (File, error)
} }
// Buffer is adaptor to TempFile // DocumentFs is adaptor to TempFile
type Buffer struct { type DocumentFs struct {
fs.FileSystem fs.FileSystem
} }
// NewDocumentFs returns an instalce of DocumentFs
func NewDocumentFs() FileSystem {
return &DocumentFs{FileSystem: fs.MakeRealFS()}
}
// TempFile creates file in temporary filesystem, at default os.TempDir // TempFile creates file in temporary filesystem, at default os.TempDir
func (b Buffer) TempFile(tmpDir string, prefix string) (File, error) { func (dfs DocumentFs) TempFile(tmpDir string, prefix string) (File, error) {
return ioutil.TempFile(tmpDir, prefix) return ioutil.TempFile(tmpDir, prefix)
} }

View File

@ -5,7 +5,6 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
cmdutil "k8s.io/kubectl/pkg/cmd/util" cmdutil "k8s.io/kubectl/pkg/cmd/util"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"opendev.org/airship/airshipctl/pkg/document" "opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/pkg/log" "opendev.org/airship/airshipctl/pkg/log"
@ -17,7 +16,7 @@ import (
type Kubectl struct { type Kubectl struct {
cmdutil.Factory cmdutil.Factory
genericclioptions.IOStreams genericclioptions.IOStreams
FileSystem document.FileSystem
// Directory to buffer documents before passing them to kubectl commands // Directory to buffer documents before passing them to kubectl commands
// default is empty, this means that /tmp dir will be used // default is empty, this means that /tmp dir will be used
bufferDir string bufferDir string
@ -33,7 +32,7 @@ func NewKubectl(f cmdutil.Factory) *Kubectl {
Out: os.Stdout, Out: os.Stdout,
ErrOut: os.Stderr, ErrOut: os.Stderr,
}, },
FileSystem: Buffer{FileSystem: fs.MakeRealFS()}, FileSystem: document.NewDocumentFs(),
} }
} }
@ -49,7 +48,7 @@ func (kubectl *Kubectl) Apply(docs []document.Document, ao *ApplyOptions) error
return err return err
} }
defer func(f File) { defer func(f document.File) {
fName := f.Name() fName := f.Name()
dErr := kubectl.RemoveAll(fName) dErr := kubectl.RemoveAll(fName)
if dErr != nil { if dErr != nil {

View File

@ -6,8 +6,8 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/pkg/k8s/kubectl" "opendev.org/airship/airshipctl/pkg/k8s/kubectl"
k8sutils "opendev.org/airship/airshipctl/pkg/k8s/utils" k8sutils "opendev.org/airship/airshipctl/pkg/k8s/utils"
"opendev.org/airship/airshipctl/testutil" "opendev.org/airship/airshipctl/testutil"
@ -24,17 +24,17 @@ var (
type MockFileSystem struct { type MockFileSystem struct {
MockRemoveAll func() error MockRemoveAll func() error
MockTempFile func() (kubectl.File, error) MockTempFile func() (document.File, error)
fs.FileSystem document.FileSystem
} }
func (fsys MockFileSystem) RemoveAll(name string) error { return fsys.MockRemoveAll() } func (fsys MockFileSystem) RemoveAll(name string) error { return fsys.MockRemoveAll() }
func (fsys MockFileSystem) TempFile(bufferDir string, prefix string) (kubectl.File, error) { func (fsys MockFileSystem) TempFile(bufferDir string, prefix string) (document.File, error) {
return fsys.MockTempFile() return fsys.MockTempFile()
} }
type TestFile struct { type TestFile struct {
kubectl.File document.File
MockName func() string MockName func() string
MockWrite func() (int, error) MockWrite func() (int, error)
MockClose func() error MockClose func() error
@ -69,13 +69,13 @@ func TestApply(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
expectedErr error expectedErr error
fs kubectl.FileSystem fs document.FileSystem
}{ }{
{ {
expectedErr: nil, expectedErr: nil,
fs: MockFileSystem{ fs: MockFileSystem{
MockRemoveAll: func() error { return nil }, MockRemoveAll: func() error { return nil },
MockTempFile: func() (kubectl.File, error) { MockTempFile: func() (document.File, error) {
return TestFile{ return TestFile{
MockName: func() string { return filenameRC }, MockName: func() string { return filenameRC },
MockWrite: func() (int, error) { return 0, nil }, MockWrite: func() (int, error) { return 0, nil },
@ -87,13 +87,13 @@ func TestApply(t *testing.T) {
{ {
expectedErr: writeOutError, expectedErr: writeOutError,
fs: MockFileSystem{ fs: MockFileSystem{
MockTempFile: func() (kubectl.File, error) { return nil, writeOutError }}, MockTempFile: func() (document.File, error) { return nil, writeOutError }},
}, },
{ {
expectedErr: TempFileError, expectedErr: TempFileError,
fs: MockFileSystem{ fs: MockFileSystem{
MockRemoveAll: func() error { return nil }, MockRemoveAll: func() error { return nil },
MockTempFile: func() (kubectl.File, error) { MockTempFile: func() (document.File, error) {
return TestFile{ return TestFile{
MockWrite: func() (int, error) { return 0, TempFileError }, MockWrite: func() (int, error) { return 0, TempFileError },
MockName: func() string { return filenameRC }, MockName: func() string { return filenameRC },

View File

@ -11,8 +11,6 @@ import (
"opendev.org/airship/airshipctl/pkg/environment" "opendev.org/airship/airshipctl/pkg/environment"
alog "opendev.org/airship/airshipctl/pkg/log" alog "opendev.org/airship/airshipctl/pkg/log"
"opendev.org/airship/airshipctl/pkg/remote/redfish" "opendev.org/airship/airshipctl/pkg/remote/redfish"
"sigs.k8s.io/kustomize/v3/pkg/fs"
) )
const ( const (
@ -82,7 +80,7 @@ func getRemoteDirectConfig(settings *environment.AirshipCTLSettings) (*config.Re
// TODO (dukov) replace with the appropriate function once it's available // TODO (dukov) replace with the appropriate function once it's available
// in document module // in document module
docBundle, err := document.NewBundle(fs.MakeRealFS(), manifest.TargetPath, "") docBundle, err := document.NewBundle(document.NewDocumentFs(), manifest.TargetPath, "")
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }

View File

@ -17,10 +17,10 @@ import (
// will iterate over the files in fixtureDir, which is a directory relative // will iterate over the files in fixtureDir, which is a directory relative
// to the tests themselves, and will write each of those files (preserving // to the tests themselves, and will write each of those files (preserving
// names) to an in-memory file system and return that fs // names) to an in-memory file system and return that fs
func SetupTestFs(t *testing.T, fixtureDir string) fs.FileSystem { func SetupTestFs(t *testing.T, fixtureDir string) document.FileSystem {
t.Helper() t.Helper()
x := fs.MakeFakeFS() x := &document.DocumentFs{FileSystem: fs.MakeFakeFS()}
files, err := ioutil.ReadDir(fixtureDir) files, err := ioutil.ReadDir(fixtureDir)
require.NoErrorf(t, err, "Failed to read fixture directory %s", fixtureDir) require.NoErrorf(t, err, "Failed to read fixture directory %s", fixtureDir)