github.com/xeptore/docker-cli@v20.10.14+incompatible/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  	flags.SetAnnotation("kubeconfig", "kubernetes", nil)
    50  	flags.SetAnnotation("kubeconfig", "deprecated", nil)
    51  	return cmd
    52  }
    53  
    54  func writeTo(dockerCli command.Cli, reader io.Reader, dest string) error {
    55  	var writer io.Writer
    56  	var printDest bool
    57  	if dest == "-" {
    58  		if dockerCli.Out().IsTerminal() {
    59  			return errors.New("cowardly refusing to export to a terminal, please specify a file path")
    60  		}
    61  		writer = dockerCli.Out()
    62  	} else {
    63  		f, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
    64  		if err != nil {
    65  			return err
    66  		}
    67  		defer f.Close()
    68  		writer = f
    69  		printDest = true
    70  	}
    71  	if _, err := io.Copy(writer, reader); err != nil {
    72  		return err
    73  	}
    74  	if printDest {
    75  		fmt.Fprintf(dockerCli.Err(), "Written file %q\n", dest)
    76  	}
    77  	return nil
    78  }
    79  
    80  // RunExport exports a Docker context
    81  func RunExport(dockerCli command.Cli, opts *ExportOptions) error {
    82  	if err := store.ValidateContextName(opts.ContextName); err != nil && opts.ContextName != command.DefaultContextName {
    83  		return err
    84  	}
    85  	ctxMeta, err := dockerCli.ContextStore().GetMetadata(opts.ContextName)
    86  	if err != nil {
    87  		return err
    88  	}
    89  	if !opts.Kubeconfig {
    90  		reader := store.Export(opts.ContextName, dockerCli.ContextStore())
    91  		defer reader.Close()
    92  		return writeTo(dockerCli, reader, opts.Dest)
    93  	}
    94  	kubernetesEndpointMeta := kubernetes.EndpointFromContext(ctxMeta)
    95  	if kubernetesEndpointMeta == nil {
    96  		return fmt.Errorf("context %q has no kubernetes endpoint", opts.ContextName)
    97  	}
    98  	kubernetesEndpoint, err := kubernetesEndpointMeta.WithTLSData(dockerCli.ContextStore(), opts.ContextName)
    99  	if err != nil {
   100  		return err
   101  	}
   102  	kubeConfig := kubernetesEndpoint.KubernetesConfig()
   103  	rawCfg, err := kubeConfig.RawConfig()
   104  	if err != nil {
   105  		return err
   106  	}
   107  	data, err := clientcmd.Write(rawCfg)
   108  	if err != nil {
   109  		return err
   110  	}
   111  	return writeTo(dockerCli, bytes.NewBuffer(data), opts.Dest)
   112  }