Move ManifestReader creation into Provider

This commit is contained in:
Sean Sullivan 2020-09-02 15:54:05 -07:00
parent 5198c54c7a
commit 62bb7972ad
7 changed files with 117 additions and 121 deletions

View File

@ -18,13 +18,11 @@ import (
"sigs.k8s.io/cli-utils/pkg/apply"
"sigs.k8s.io/cli-utils/pkg/common"
"sigs.k8s.io/cli-utils/pkg/inventory"
"sigs.k8s.io/cli-utils/pkg/manifestreader"
"sigs.k8s.io/cli-utils/pkg/provider"
"sigs.k8s.io/kustomize/kyaml/setters2"
)
func GetApplyRunner(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *ApplyRunner {
provider := provider.NewProvider(f, inventory.WrapInventoryObj)
func GetApplyRunner(provider provider.Provider, ioStreams genericclioptions.IOStreams) *ApplyRunner {
r := &ApplyRunner{
Applier: apply.NewApplier(provider, ioStreams),
ioStreams: ioStreams,
@ -71,7 +69,8 @@ func GetApplyRunner(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *A
}
func ApplyCommand(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
return GetApplyRunner(f, ioStreams).Command
provider := provider.NewProvider(f, inventory.WrapInventoryObj)
return GetApplyRunner(provider, ioStreams).Command
}
type ApplyRunner struct {
@ -116,35 +115,7 @@ func (r *ApplyRunner) RunE(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
// Fetch the namespace from the configloader. The source of this
// either the namespace flag or the context. If the namespace is provided
// with the flag, enforceNamespace will be true. In this case, it is
// an error if any of the resources in the package has a different
// namespace set.
namespace, enforceNamespace, err := r.provider.Factory().ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}
var reader manifestreader.ManifestReader
readerOptions := manifestreader.ReaderOptions{
Factory: r.provider.Factory(),
Namespace: namespace,
EnforceNamespace: enforceNamespace,
}
if len(args) == 0 {
reader = &manifestreader.StreamManifestReader{
ReaderName: "stdin",
Reader: cmd.InOrStdin(),
ReaderOptions: readerOptions,
}
} else {
reader = &manifestreader.PathManifestReader{
Path: args[0],
ReaderOptions: readerOptions,
}
}
reader := r.provider.ManifestReader(cmd.InOrStdin(), args)
infos, err := reader.Read()
if err != nil {
return err

View File

@ -15,11 +15,11 @@ import (
)
// GetDestroyRunner creates and returns the DestroyRunner which stores the cobra command.
func GetDestroyRunner(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *DestroyRunner {
provider := provider.NewProvider(f, inventory.WrapInventoryObj)
func GetDestroyRunner(provider provider.Provider, ioStreams genericclioptions.IOStreams) *DestroyRunner {
r := &DestroyRunner{
Destroyer: apply.NewDestroyer(provider, ioStreams),
ioStreams: ioStreams,
provider: provider,
}
cmd := &cobra.Command{
Use: "destroy (DIRECTORY | STDIN)",
@ -48,7 +48,8 @@ func GetDestroyRunner(f cmdutil.Factory, ioStreams genericclioptions.IOStreams)
// DestroyCommand creates the DestroyRunner, returning the cobra command associated with it.
func DestroyCommand(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
return GetDestroyRunner(f, ioStreams).Command
provider := provider.NewProvider(f, inventory.WrapInventoryObj)
return GetDestroyRunner(provider, ioStreams).Command
}
// DestroyRunner encapsulates data necessary to run the destroy command.
@ -56,6 +57,7 @@ type DestroyRunner struct {
Command *cobra.Command
ioStreams genericclioptions.IOStreams
Destroyer *apply.Destroyer
provider provider.Provider
}
func (r *DestroyRunner) RunE(cmd *cobra.Command, args []string) error {
@ -64,9 +66,20 @@ func (r *DestroyRunner) RunE(cmd *cobra.Command, args []string) error {
return err
}
// Retrieve the inventory object.
reader := r.provider.ManifestReader(cmd.InOrStdin(), args)
infos, err := reader.Read()
if err != nil {
return err
}
inv, _, err := inventory.SplitInfos(infos)
if err != nil {
return err
}
// Run the destroyer. It will return a channel where we can receive updates
// to keep track of progress and any issues.
ch := r.Destroyer.Run()
ch := r.Destroyer.Run(inv)
// The printer will print updates from the channel. It will block
// until the channel is closed.

View File

@ -15,7 +15,6 @@ import (
"sigs.k8s.io/cli-utils/pkg/apply/event"
"sigs.k8s.io/cli-utils/pkg/common"
"sigs.k8s.io/cli-utils/pkg/inventory"
"sigs.k8s.io/cli-utils/pkg/manifestreader"
"sigs.k8s.io/cli-utils/pkg/provider"
"sigs.k8s.io/kustomize/kyaml/setters2"
)
@ -27,8 +26,7 @@ var (
)
// GetPreviewRunner creates and returns the PreviewRunner which stores the cobra command.
func GetPreviewRunner(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *PreviewRunner {
provider := provider.NewProvider(f, inventory.WrapInventoryObj)
func GetPreviewRunner(provider provider.Provider, ioStreams genericclioptions.IOStreams) *PreviewRunner {
r := &PreviewRunner{
Applier: apply.NewApplier(provider, ioStreams),
Destroyer: apply.NewDestroyer(provider, ioStreams),
@ -68,7 +66,8 @@ func GetPreviewRunner(f cmdutil.Factory, ioStreams genericclioptions.IOStreams)
// PreviewCommand creates the PreviewRunner, returning the cobra command associated with it.
func PreviewCommand(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
return GetPreviewRunner(f, ioStreams).Command
provider := provider.NewProvider(f, inventory.WrapInventoryObj)
return GetPreviewRunner(provider, ioStreams).Command
}
// PreviewRunner encapsulates data necessary to run the preview command.
@ -101,6 +100,12 @@ func (r *PreviewRunner) RunE(cmd *cobra.Command, args []string) error {
r.Destroyer.DryRunStrategy = drs
}
reader := r.provider.ManifestReader(cmd.InOrStdin(), args)
infos, err := reader.Read()
if err != nil {
return err
}
// if destroy flag is set in preview, transmit it to destroyer DryRunStrategy flag
// and pivot execution to destroy with dry-run
if !r.Destroyer.DryRunStrategy.ClientOrServerDryRun() {
@ -117,39 +122,6 @@ func (r *PreviewRunner) RunE(cmd *cobra.Command, args []string) error {
return err
}
// Fetch the namespace from the configloader. The source of this
// either the namespace flag or the context. If the namespace is provided
// with the flag, enforceNamespace will be true. In this case, it is
// an error if any of the resources in the package has a different
// namespace set.
namespace, enforceNamespace, err := r.provider.Factory().ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}
var reader manifestreader.ManifestReader
readerOptions := manifestreader.ReaderOptions{
Factory: r.provider.Factory(),
Namespace: namespace,
EnforceNamespace: enforceNamespace,
}
if len(args) == 0 {
reader = &manifestreader.StreamManifestReader{
ReaderName: "stdin",
Reader: cmd.InOrStdin(),
ReaderOptions: readerOptions,
}
} else {
reader = &manifestreader.PathManifestReader{
Path: args[0],
ReaderOptions: readerOptions,
}
}
infos, err := reader.Read()
if err != nil {
return err
}
// Run the applier. It will return a channel where we can receive updates
// to keep track of progress and any issues.
ch = r.Applier.Run(ctx, infos, apply.Options{
@ -158,7 +130,11 @@ func (r *PreviewRunner) RunE(cmd *cobra.Command, args []string) error {
DryRunStrategy: drs,
})
} else {
ch = r.Destroyer.Run()
inv, _, err := inventory.SplitInfos(infos)
if err != nil {
return err
}
ch = r.Destroyer.Run(inv)
}
// The printer will print updates from the channel. It will block

View File

@ -10,7 +10,6 @@ import (
"github.com/go-errors/errors"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"sigs.k8s.io/cli-utils/cmd/status/printers"
@ -22,7 +21,6 @@ import (
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/collector"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/event"
"sigs.k8s.io/cli-utils/pkg/kstatus/status"
"sigs.k8s.io/cli-utils/pkg/manifestreader"
"sigs.k8s.io/cli-utils/pkg/provider"
"sigs.k8s.io/cli-utils/pkg/util/factory"
)
@ -76,23 +74,7 @@ func (r *StatusRunner) runE(cmd *cobra.Command, args []string) error {
return err
}
var reader manifestreader.ManifestReader
readerOptions := manifestreader.ReaderOptions{
Factory: r.provider.Factory(),
Namespace: metav1.NamespaceDefault,
}
if len(args) == 0 {
reader = &manifestreader.StreamManifestReader{
ReaderName: "stdin",
Reader: cmd.InOrStdin(),
ReaderOptions: readerOptions,
}
} else {
reader = &manifestreader.PathManifestReader{
Path: args[0],
ReaderOptions: readerOptions,
}
}
reader := r.provider.ManifestReader(cmd.InOrStdin(), args)
infos, err := reader.Read()
if err != nil {
return err

View File

@ -78,51 +78,50 @@ func (d *Destroyer) Initialize(cmd *cobra.Command, paths []string) error {
return nil
}
// Run performs the destroy step. This happens asynchronously
// on progress and any errors are reported back on the event channel.
func (d *Destroyer) Run() <-chan event.Event {
// Run performs the destroy step. Passes the inventory object. This
// happens asynchronously on progress and any errors are reported
// back on the event channel.
func (d *Destroyer) Run(inv *resource.Info) <-chan event.Event {
ch := make(chan event.Event)
go func() {
defer close(ch)
d.invClient.SetDryRunStrategy(d.DryRunStrategy)
infos, err := d.ApplyOptions.GetObjects()
if err != nil {
ch <- event.Event{
Type: event.ErrorType,
ErrorEvent: event.ErrorEvent{
Err: errors.WrapPrefix(err, "error reading resource manifests", 1),
},
}
return
}
// Force a pruning of all cluster resources by clearing out the
// local resources, and sending only the inventory object to the
// prune.
invInfo, _, err := inventory.SplitInfos(infos)
if err != nil {
ch <- event.Event{
Type: event.ErrorType,
ErrorEvent: event.ErrorEvent{
Err: errors.WrapPrefix(err, "error clearing inventory object", 1),
},
}
return
}
infos = []*resource.Info{invInfo}
infos := []*resource.Info{inv}
// Start the event transformer goroutine so we can transform
// the Prune events emitted from the Prune function to Delete
// Events. That we use Prune to implement destroy is an
// implementation detail and the events should not be Prune events.
tempChannel, completedChannel := runPruneEventTransformer(ch)
err = d.PruneOptions.Prune(infos, tempChannel, prune.Options{
err := d.PruneOptions.Prune(infos, tempChannel, prune.Options{
DryRunStrategy: d.DryRunStrategy,
PropagationPolicy: metav1.DeletePropagationBackground,
})
if err != nil {
ch <- event.Event{
Type: event.ErrorType,
ErrorEvent: event.ErrorEvent{
Err: errors.WrapPrefix(err, "error pruning resources in cluster", 1),
},
}
return
}
// Now delete the inventory object as well.
if invInfo != nil {
_ = d.invClient.DeleteInventoryObj(invInfo)
err = d.invClient.DeleteInventoryObj(inv)
if err != nil {
ch <- event.Event{
Type: event.ErrorType,
ErrorEvent: event.ErrorEvent{
Err: errors.WrapPrefix(err, "error deleting inventory object", 1),
},
}
return
}
// Close the tempChannel to signal to the event transformer that

View File

@ -4,9 +4,13 @@
package provider
import (
"io"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubectl/pkg/cmd/util"
"sigs.k8s.io/cli-utils/pkg/inventory"
"sigs.k8s.io/cli-utils/pkg/manifestreader"
"sigs.k8s.io/cli-utils/pkg/object"
)
@ -35,3 +39,15 @@ func (f *FakeProvider) InventoryClient() (inventory.InventoryClient, error) {
func (f *FakeProvider) ToRESTMapper() (meta.RESTMapper, error) {
return f.factory.ToRESTMapper()
}
func (f *FakeProvider) ManifestReader(reader io.Reader, args []string) manifestreader.ManifestReader {
readerOptions := manifestreader.ReaderOptions{
Factory: f.factory,
Namespace: metav1.NamespaceDefault,
}
return &manifestreader.StreamManifestReader{
ReaderName: "stdin",
Reader: reader,
ReaderOptions: readerOptions,
}
}

View File

@ -4,9 +4,13 @@
package provider
import (
"io"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubectl/pkg/cmd/util"
"sigs.k8s.io/cli-utils/pkg/inventory"
"sigs.k8s.io/cli-utils/pkg/manifestreader"
)
// Provider is an interface which wraps the kubectl factory and
@ -15,6 +19,7 @@ type Provider interface {
Factory() util.Factory
InventoryClient() (inventory.InventoryClient, error)
ToRESTMapper() (meta.RESTMapper, error)
ManifestReader(reader io.Reader, args []string) manifestreader.ManifestReader
}
// InventoryProvider implements the Provider interface.
@ -46,3 +51,37 @@ func (f *InventoryProvider) InventoryClient() (inventory.InventoryClient, error)
func (f *InventoryProvider) ToRESTMapper() (meta.RESTMapper, error) {
return f.factory.ToRESTMapper()
}
func (f *InventoryProvider) ManifestReader(reader io.Reader, args []string) manifestreader.ManifestReader {
// Fetch the namespace from the configloader. The source of this
// either the namespace flag or the context. If the namespace is provided
// with the flag, enforceNamespace will be true. In this case, it is
// an error if any of the resources in the package has a different
// namespace set.
namespace, enforceNamespace, err := f.factory.ToRawKubeConfigLoader().Namespace()
if err != nil {
namespace = metav1.NamespaceDefault
enforceNamespace = false
}
readerOptions := manifestreader.ReaderOptions{
Factory: f.factory,
Namespace: namespace,
EnforceNamespace: enforceNamespace,
}
var mReader manifestreader.ManifestReader
if len(args) == 0 {
mReader = &manifestreader.StreamManifestReader{
ReaderName: "stdin",
Reader: reader,
ReaderOptions: readerOptions,
}
} else {
mReader = &manifestreader.PathManifestReader{
Path: args[0],
ReaderOptions: readerOptions,
}
}
return mReader
}