convert.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package cmd
  14. import (
  15. "fmt"
  16. "io"
  17. "os"
  18. "github.com/renstrom/dedent"
  19. "k8s.io/kubernetes/pkg/api"
  20. "k8s.io/kubernetes/pkg/api/unversioned"
  21. "k8s.io/kubernetes/pkg/apimachinery/registered"
  22. "k8s.io/kubernetes/pkg/kubectl"
  23. cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
  24. "k8s.io/kubernetes/pkg/kubectl/resource"
  25. "k8s.io/kubernetes/pkg/runtime"
  26. "github.com/spf13/cobra"
  27. )
  28. var (
  29. convert_long = dedent.Dedent(`
  30. Convert config files between different API versions. Both YAML
  31. and JSON formats are accepted.
  32. The command takes filename, directory, or URL as input, and convert it into format
  33. of version specified by --output-version flag. If target version is not specified or
  34. not supported, convert to latest version.
  35. The default output will be printed to stdout in YAML format. One can use -o option
  36. to change to output destination.
  37. `)
  38. convert_example = dedent.Dedent(`
  39. # Convert 'pod.yaml' to latest version and print to stdout.
  40. kubectl convert -f pod.yaml
  41. # Convert the live state of the resource specified by 'pod.yaml' to the latest version
  42. # and print to stdout in json format.
  43. kubectl convert -f pod.yaml --local -o json
  44. # Convert all files under current directory to latest version and create them all.
  45. kubectl convert -f . | kubectl create -f -
  46. `)
  47. )
  48. // NewCmdConvert creates a command object for the generic "convert" action, which
  49. // translates the config file into a given version.
  50. func NewCmdConvert(f *cmdutil.Factory, out io.Writer) *cobra.Command {
  51. options := &ConvertOptions{}
  52. cmd := &cobra.Command{
  53. Use: "convert -f FILENAME",
  54. Short: "Convert config files between different API versions",
  55. Long: convert_long,
  56. Example: convert_example,
  57. Run: func(cmd *cobra.Command, args []string) {
  58. err := options.Complete(f, out, cmd, args)
  59. cmdutil.CheckErr(err)
  60. err = options.RunConvert()
  61. cmdutil.CheckErr(err)
  62. },
  63. }
  64. usage := "Filename, directory, or URL to file to need to get converted."
  65. kubectl.AddJsonFilenameFlag(cmd, &options.filenames, usage)
  66. cmdutil.AddRecursiveFlag(cmd, &options.recursive)
  67. cmd.MarkFlagRequired("filename")
  68. cmdutil.AddValidateFlags(cmd)
  69. cmdutil.AddPrinterFlags(cmd)
  70. cmd.Flags().BoolVar(&options.local, "local", true, "If true, convert will NOT try to contact api-server but run locally.")
  71. cmdutil.AddInclude3rdPartyFlags(cmd)
  72. return cmd
  73. }
  74. // ConvertOptions have the data required to perform the convert operation
  75. type ConvertOptions struct {
  76. builder *resource.Builder
  77. filenames []string
  78. local bool
  79. encoder runtime.Encoder
  80. out io.Writer
  81. printer kubectl.ResourcePrinter
  82. outputVersion unversioned.GroupVersion
  83. recursive bool
  84. }
  85. // Complete collects information required to run Convert command from command line.
  86. func (o *ConvertOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) (err error) {
  87. o.outputVersion, err = cmdutil.OutputVersion(cmd, &registered.EnabledVersionsForGroup(api.GroupName)[0])
  88. if err != nil {
  89. return err
  90. }
  91. if !registered.IsEnabledVersion(o.outputVersion) {
  92. cmdutil.UsageError(cmd, "'%s' is not a registered version.", o.outputVersion)
  93. }
  94. // build the builder
  95. mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
  96. clientMapper := resource.ClientMapperFunc(f.ClientForMapping)
  97. if o.local {
  98. fmt.Fprintln(os.Stderr, "running in local mode...")
  99. o.builder = resource.NewBuilder(mapper, typer, resource.DisabledClientForMapping{ClientMapper: clientMapper}, f.Decoder(true))
  100. } else {
  101. o.builder = resource.NewBuilder(mapper, typer, clientMapper, f.Decoder(true))
  102. schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir"))
  103. if err != nil {
  104. return err
  105. }
  106. o.builder = o.builder.Schema(schema)
  107. }
  108. cmdNamespace, _, err := f.DefaultNamespace()
  109. if err != nil {
  110. return err
  111. }
  112. o.builder = o.builder.NamespaceParam(cmdNamespace).
  113. ContinueOnError().
  114. FilenameParam(false, o.recursive, o.filenames...).
  115. Flatten()
  116. // build the printer
  117. o.out = out
  118. outputFormat := cmdutil.GetFlagString(cmd, "output")
  119. templateFile := cmdutil.GetFlagString(cmd, "template")
  120. if len(outputFormat) == 0 {
  121. if len(templateFile) == 0 {
  122. outputFormat = "yaml"
  123. } else {
  124. outputFormat = "template"
  125. }
  126. }
  127. o.encoder = f.JSONEncoder()
  128. o.printer, _, err = kubectl.GetPrinter(outputFormat, templateFile, false)
  129. if err != nil {
  130. return err
  131. }
  132. return nil
  133. }
  134. // RunConvert implements the generic Convert command
  135. func (o *ConvertOptions) RunConvert() error {
  136. r := o.builder.Do()
  137. err := r.Err()
  138. if err != nil {
  139. return err
  140. }
  141. count := 0
  142. err = r.Visit(func(info *resource.Info, err error) error {
  143. if err != nil {
  144. return err
  145. }
  146. infos := []*resource.Info{info}
  147. objects, err := resource.AsVersionedObject(infos, false, o.outputVersion, o.encoder)
  148. if err != nil {
  149. return err
  150. }
  151. count++
  152. return o.printer.PrintObj(objects, o.out)
  153. })
  154. if err != nil {
  155. return err
  156. }
  157. if count == 0 {
  158. return fmt.Errorf("no objects passed to convert")
  159. }
  160. return nil
  161. }