github.com/itscaro/cli@v0.0.0-20190705081621-c9db0fe93829/cli/command/context/export.go (about)

     1  package context
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"os"
     9  
    10  	"github.com/docker/cli/cli"
    11  	"github.com/docker/cli/cli/command"
    12  	"github.com/docker/cli/cli/context/kubernetes"
    13  	"github.com/docker/cli/cli/context/store"
    14  	"github.com/spf13/cobra"
    15  	"k8s.io/client-go/tools/clientcmd"
    16  )
    17  
    18  // ExportOptions are the options used for exporting a context
    19  type ExportOptions struct {
    20  	Kubeconfig  bool
    21  	ContextName string
    22  	Dest        string
    23  }
    24  
    25  func newExportCommand(dockerCli command.Cli) *cobra.Command {
    26  	opts := &ExportOptions{}
    27  	cmd := &cobra.Command{
    28  		Use:   "export [OPTIONS] CONTEXT [FILE|-]",
    29  		Short: "Export a context to a tar or kubeconfig file",
    30  		Args:  cli.RequiresRangeArgs(1, 2),
    31  		RunE: func(cmd *cobra.Command, args []string) error {
    32  			opts.ContextName = args[0]
    33  			if len(args) == 2 {
    34  				opts.Dest = args[1]
    35  			} else {
    36  				opts.Dest = opts.ContextName
    37  				if opts.Kubeconfig {
    38  					opts.Dest += ".kubeconfig"
    39  				} else {
    40  					opts.Dest += ".dockercontext"
    41  				}
    42  			}
    43  			return RunExport(dockerCli, opts)
    44  		},
    45  	}
    46  
    47  	flags := cmd.Flags()
    48  	flags.BoolVar(&opts.Kubeconfig, "kubeconfig", false, "Export as a kubeconfig file")
    49  	return cmd
    50  }
    51  
    52  func writeTo(dockerCli command.Cli, reader io.Reader, dest string) error {
    53  	var writer io.Writer
    54  	var printDest bool
    55  	if dest == "-" {
    56  		if dockerCli.Out().IsTerminal() {
    57  			return errors.New("cowardly refusing to export to a terminal, please specify a file path")
    58  		}
    59  		writer = dockerCli.Out()
    60  	} else {
    61  		f, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
    62  		if err != nil {
    63  			return err
    64  		}
    65  		defer f.Close()
    66  		writer = f
    67  		printDest = true
    68  	}
    69  	if _, err := io.Copy(writer, reader); err != nil {
    70  		return err
    71  	}
    72  	if printDest {
    73  		fmt.Fprintf(dockerCli.Err(), "Written file %q\n", dest)
    74  	}
    75  	return nil
    76  }
    77  
    78  // RunExport exports a Docker context
    79  func RunExport(dockerCli command.Cli, opts *ExportOptions) error {
    80  	if err := validateContextName(opts.ContextName); err != nil && opts.ContextName != command.DefaultContextName {
    81  		return err
    82  	}
    83  	ctxMeta, err := dockerCli.ContextStore().GetMetadata(opts.ContextName)
    84  	if err != nil {
    85  		return err
    86  	}
    87  	if !opts.Kubeconfig {
    88  		reader := store.Export(opts.ContextName, dockerCli.ContextStore())
    89  		defer reader.Close()
    90  		return writeTo(dockerCli, reader, opts.Dest)
    91  	}
    92  	kubernetesEndpointMeta := kubernetes.EndpointFromContext(ctxMeta)
    93  	if kubernetesEndpointMeta == nil {
    94  		return fmt.Errorf("context %q has no kubernetes endpoint", opts.ContextName)
    95  	}
    96  	kubernetesEndpoint, err := kubernetesEndpointMeta.WithTLSData(dockerCli.ContextStore(), opts.ContextName)
    97  	if err != nil {
    98  		return err
    99  	}
   100  	kubeConfig := kubernetesEndpoint.KubernetesConfig()
   101  	rawCfg, err := kubeConfig.RawConfig()
   102  	if err != nil {
   103  		return err
   104  	}
   105  	data, err := clientcmd.Write(rawCfg)
   106  	if err != nil {
   107  		return err
   108  	}
   109  	return writeTo(dockerCli, bytes.NewBuffer(data), opts.Dest)
   110  }