pkg/cmd/cli/cmd/export.go
9451c85d
 package cmd
 
 import (
 	"fmt"
 	"io"
 	"os"
 
 	"github.com/spf13/cobra"
 
83c702b4
 	kapi "k8s.io/kubernetes/pkg/api"
 	"k8s.io/kubernetes/pkg/kubectl"
95ec120f
 	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
83c702b4
 	"k8s.io/kubernetes/pkg/kubectl/resource"
 	"k8s.io/kubernetes/pkg/runtime"
 	utilerrors "k8s.io/kubernetes/pkg/util/errors"
9451c85d
 
6267dded
 	"github.com/openshift/origin/pkg/cmd/templates"
95ec120f
 	cmdutil "github.com/openshift/origin/pkg/cmd/util"
9451c85d
 	"github.com/openshift/origin/pkg/cmd/util/clientcmd"
 	templateapi "github.com/openshift/origin/pkg/template/api"
 )
 
6267dded
 var (
 	exportLong = templates.LongDesc(`
 		Export resources so they can be used elsewhere
9451c85d
 
6267dded
 		The export command makes it easy to take existing objects and convert them to configuration files
 		for backups or for creating elsewhere in the cluster. Fields that cannot be specified on create
 		will be set to empty, and any field which is assigned on creation (like a service's clusterIP, or
 		a deployment config's latestVersion). The status part of objects is also cleared.
9451c85d
 
6267dded
 		Some fields like clusterIP may be useful when exporting an application from one cluster to apply
 		to another - assuming another service on the destination cluster does not already use that IP.
 		The --exact flag will instruct export to not clear fields that might be useful. You may also use
 		--raw to get the exact values for an object - useful for converting a file on disk between API
 		versions.
9451c85d
 
6267dded
 		Another use case for export is to create reusable templates for applications. Pass --as-template
 		to generate the API structure for a template to which you can add parameters and object labels.`)
9451c85d
 
6267dded
 	exportExample = templates.Examples(`
 		# export the services and deployment configurations labeled name=test
 	  %[1]s export svc,dc -l name=test
9451c85d
 
6267dded
 	  # export all services to a template
 	  %[1]s export service --as-template=test
9451c85d
 
6267dded
 	  # export to JSON
 	  %[1]s export service -o json`)
9451c85d
 )
 
 func NewCmdExport(fullName string, f *clientcmd.Factory, in io.Reader, out io.Writer) *cobra.Command {
011833a5
 	exporter := &DefaultExporter{}
5997bb61
 	var filenames []string
9451c85d
 	cmd := &cobra.Command{
 		Use:     "export RESOURCE/NAME ... [options]",
 		Short:   "Export resources so they can be used elsewhere",
 		Long:    exportLong,
 		Example: fmt.Sprintf(exportExample, fullName),
 		Run: func(cmd *cobra.Command, args []string) {
 			err := RunExport(f, exporter, in, out, cmd, args, filenames)
95ec120f
 			if err == cmdutil.ErrExit {
9451c85d
 				os.Exit(1)
 			}
95ec120f
 			kcmdutil.CheckErr(err)
9451c85d
 		},
 	}
cc24e574
 	cmd.Flags().String("as-template", "", "Output a Template object with specified name instead of a List or single object.")
e0c8f93b
 	cmd.Flags().Bool("exact", false, "Preserve fields that may be cluster specific, such as service clusterIPs or generated names")
9451c85d
 	cmd.Flags().Bool("raw", false, "If true, do not alter the resources in any way after they are loaded.")
 	cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
6dc128c2
 	cmd.Flags().Bool("all-namespaces", false, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.")
3976cf48
 	cmd.Flags().StringSliceVarP(&filenames, "filename", "f", filenames, "Filename, directory, or URL to file for the resource to export.")
a166f955
 	cmd.MarkFlagFilename("filename")
08ed35ca
 	cmd.Flags().Bool("all", true, "DEPRECATED: all is ignored, specifying a resource without a name selects all the instances of that resource")
7074a380
 	cmd.Flags().MarkDeprecated("all", "all is ignored because specifying a resource without a name selects all the instances of that resource")
95ec120f
 	kcmdutil.AddPrinterFlags(cmd)
9451c85d
 	return cmd
 }
 
5997bb61
 func RunExport(f *clientcmd.Factory, exporter Exporter, in io.Reader, out io.Writer, cmd *cobra.Command, args []string, filenames []string) error {
95ec120f
 	selector := kcmdutil.GetFlagString(cmd, "selector")
 	allNamespaces := kcmdutil.GetFlagBool(cmd, "all-namespaces")
 	exact := kcmdutil.GetFlagBool(cmd, "exact")
 	asTemplate := kcmdutil.GetFlagString(cmd, "as-template")
 	raw := kcmdutil.GetFlagBool(cmd, "raw")
9451c85d
 	if exact && raw {
95ec120f
 		return kcmdutil.UsageError(cmd, "--exact and --raw may not both be specified")
9451c85d
 	}
 
 	clientConfig, err := f.ClientConfig()
 	if err != nil {
 		return err
 	}
95ec120f
 	outputVersion, err := kcmdutil.OutputVersion(cmd, clientConfig.GroupVersion)
03c2a2bd
 	if err != nil {
 		return err
 	}
9451c85d
 
ab7d732c
 	cmdNamespace, explicit, err := f.DefaultNamespace()
9451c85d
 	if err != nil {
 		return err
 	}
 
59e6f9d2
 	mapper, typer := f.Object(false)
a3581b14
 	b := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), kapi.Codecs.UniversalDecoder()).
6dc128c2
 		NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces).
c5dc7f15
 		FilenameParam(explicit, false, filenames...).
9451c85d
 		SelectorParam(selector).
7074a380
 		ResourceTypeOrNameArgs(true, args...).
9451c85d
 		Flatten()
 
 	one := false
 	infos, err := b.Do().IntoSingular(&one).Infos()
 	if err != nil {
 		return err
 	}
 
 	if len(infos) == 0 {
 		return fmt.Errorf("no resources found - nothing to export")
 	}
 
 	if !raw {
 		newInfos := []*resource.Info{}
 		errs := []error{}
 		for _, info := range infos {
 			if err := exporter.Export(info.Object, exact); err != nil {
 				if err == ErrExportOmit {
 					continue
 				}
 				errs = append(errs, err)
 			}
 			newInfos = append(newInfos, info)
 		}
 		if len(errs) > 0 {
 			return utilerrors.NewAggregate(errs)
 		}
 		infos = newInfos
 	}
 
 	var result runtime.Object
cc24e574
 	if len(asTemplate) > 0 {
8201efbe
 		objects, err := resource.AsVersionedObjects(infos, outputVersion, kapi.Codecs.LegacyCodec(outputVersion))
9451c85d
 		if err != nil {
 			return err
 		}
 		template := &templateapi.Template{
 			Objects: objects,
 		}
cc24e574
 		template.Name = asTemplate
8201efbe
 		result, err = kapi.Scheme.ConvertToVersion(template, outputVersion)
9451c85d
 		if err != nil {
 			return err
 		}
 	} else {
8201efbe
 		object, err := resource.AsVersionedObject(infos, !one, outputVersion, kapi.Codecs.LegacyCodec(outputVersion))
9451c85d
 		if err != nil {
 			return err
 		}
 		result = object
 	}
 
 	// use YAML as the default format
95ec120f
 	outputFormat := kcmdutil.GetFlagString(cmd, "output")
 	templateFile := kcmdutil.GetFlagString(cmd, "template")
9451c85d
 	if len(outputFormat) == 0 && len(templateFile) != 0 {
 		outputFormat = "template"
 	}
 	if len(outputFormat) == 0 {
 		outputFormat = "yaml"
 	}
ddfd9fe3
 	p, _, err := kubectl.GetPrinter(outputFormat, templateFile, kcmdutil.GetFlagBool(cmd, "no-headers"))
9451c85d
 	if err != nil {
 		return err
 	}
 	return p.PrintObj(result, out)
 }