Merge pull request #18835 from brendandburns/3rdparty

Automatic merge from submit-queue

Add support for 3rd party objects to kubectl

@deads2k @jlowdermilk

Instructions for playing around with this:

Run an apiserver with third party resources turned on (`--runtime-config=extensions/v1beta1=true,extensions/v1beta1/thirdpartyresources=true`)

Then you should be able to:

```
kubectl create -f rsrc.json
```

```json
{
  "metadata": {
    "name": "foo.company.com"
  },
  "apiVersion": "extensions/v1beta1",
  "kind": "ThirdPartyResource",
  "versions": [
    {
      "apiGroup": "group",
      "name": "v1"
    },
    {
      "apiGroup": "group",
      "name": "v2"
    }
  ]
}
```

Once that is done, you should be able to:

```
curl http://<server>/apis/company.com/v1/foos
```

```
curl -X POST -d @${HOME}/foo.json http://localhost:8080/apis/company.com/v1/namespaces/default/foos
```

```json
{
  "kind": "Foo",
  "apiVersion": "company.com/v1",
  "metadata": {
    "name": "baz"
  },
  "someField": "hello world",
  "otherField": 1
}
```

After this PR, you can do:

```
kubectl create -f foo.json
```

```
kubectl get foos
```

etc.
This commit is contained in:
k8s-merge-robot
2016-03-31 18:09:56 -07:00
115 changed files with 697 additions and 148 deletions

View File

@@ -110,6 +110,7 @@ func NewCmdAnnotate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
},
}
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
cmd.Flags().StringVarP(&options.selector, "selector", "l", "", "Selector (label query) to filter on")
cmd.Flags().BoolVar(&options.overwrite, "overwrite", false, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.")
cmd.Flags().BoolVar(&options.all, "all", false, "select all resources in the namespace of the specified resource types")
@@ -161,7 +162,7 @@ func (o *AnnotateOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra
o.recordChangeCause = cmdutil.GetRecordFlag(cmd)
o.changeCause = f.Command()
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
o.builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(namespace).DefaultNamespace().
@@ -246,11 +247,13 @@ func (o AnnotateOptions) RunAnnotate() error {
if err != nil {
return err
}
mapper, _ := o.f.Object(cmdutil.GetIncludeThirdPartyAPIs(o.cmd))
outputFormat := cmdutil.GetFlagString(o.cmd, "output")
if outputFormat != "" {
return o.f.PrintObject(o.cmd, outputObj, o.out)
return o.f.PrintObject(o.cmd, mapper, outputObj, o.out)
}
mapper, _ := o.f.Object()
cmdutil.PrintSuccess(mapper, false, o.out, info.Mapping.Resource, info.Name, "annotated")
return nil
})

View File

@@ -72,6 +72,7 @@ func NewCmdApply(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -95,7 +96,7 @@ func RunApply(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *Ap
return err
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
Schema(schema).
ContinueOnError().

View File

@@ -74,6 +74,7 @@ func NewCmdAutoscale(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -88,7 +89,7 @@ func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
return err
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(namespace).DefaultNamespace().
@@ -157,7 +158,7 @@ func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
}
// TODO: extract this flag to a central location, when such a location exists.
if cmdutil.GetFlagBool(cmd, "dry-run") {
return f.PrintObject(cmd, object, out)
return f.PrintObject(cmd, mapper, object, out)
}
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), hpa, f.JSONEncoder()); err != nil {
@@ -170,7 +171,7 @@ func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
}
if len(cmdutil.GetFlagString(cmd, "output")) > 0 {
return f.PrintObject(cmd, object, out)
return f.PrintObject(cmd, mapper, object, out)
}
cmdutil.PrintSuccess(mapper, false, out, info.Mapping.Resource, info.Name, "autoscaled")
return nil

View File

@@ -42,6 +42,7 @@ func NewCmdClusterInfo(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.CheckErr(err)
},
}
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -56,7 +57,7 @@ func RunClusterInfo(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command) error
}
printService(out, "Kubernetes master", client.Host)
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
cmdNamespace := cmdutil.GetFlagString(cmd, "namespace")
if cmdNamespace == "" {
cmdNamespace = api.NamespaceSystem

View File

@@ -180,7 +180,7 @@ func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
Typer: scheme,
}
return &cmdutil.Factory{
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
Object: func(discovery bool) (meta.RESTMapper, runtime.ObjectTyper) {
priorityRESTMapper := meta.PriorityRESTMapper{
Delegate: t.Mapper,
ResourcePriority: []unversioned.GroupVersionResource{
@@ -221,7 +221,7 @@ func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
func NewMixedFactory(apiClient resource.RESTClient) (*cmdutil.Factory, *testFactory, runtime.Codec) {
f, t, c := NewTestFactory()
f.Object = func() (meta.RESTMapper, runtime.ObjectTyper) {
f.Object = func(discovery bool) (meta.RESTMapper, runtime.ObjectTyper) {
priorityRESTMapper := meta.PriorityRESTMapper{
Delegate: meta.MultiRESTMapper{t.Mapper, testapi.Default.RESTMapper()},
ResourcePriority: []unversioned.GroupVersionResource{
@@ -248,7 +248,7 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
}
f := &cmdutil.Factory{
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
Object: func(discovery bool) (meta.RESTMapper, runtime.ObjectTyper) {
return testapi.Default.RESTMapper(), api.Scheme
},
Client: func() (*client.Client, error) {
@@ -380,7 +380,8 @@ func ExamplePrintReplicationControllerWithNamespace() {
Replicas: 1,
},
}
err := f.PrintObject(cmd, ctrl, os.Stdout)
mapper, _ := f.Object(false)
err := f.PrintObject(cmd, mapper, ctrl, os.Stdout)
if err != nil {
fmt.Printf("Unexpected error: %v", err)
}
@@ -428,7 +429,8 @@ func ExamplePrintMultiContainersReplicationControllerWithWide() {
Replicas: 1,
},
}
err := f.PrintObject(cmd, ctrl, os.Stdout)
mapper, _ := f.Object(false)
err := f.PrintObject(cmd, mapper, ctrl, os.Stdout)
if err != nil {
fmt.Printf("Unexpected error: %v", err)
}
@@ -476,7 +478,8 @@ func ExamplePrintReplicationController() {
Replicas: 1,
},
}
err := f.PrintObject(cmd, ctrl, os.Stdout)
mapper, _ := f.Object(false)
err := f.PrintObject(cmd, mapper, ctrl, os.Stdout)
if err != nil {
fmt.Printf("Unexpected error: %v", err)
}
@@ -511,7 +514,8 @@ func ExamplePrintPodWithWideFormat() {
},
},
}
err := f.PrintObject(cmd, pod, os.Stdout)
mapper, _ := f.Object(false)
err := f.PrintObject(cmd, mapper, pod, os.Stdout)
if err != nil {
fmt.Printf("Unexpected error: %v", err)
}
@@ -550,7 +554,8 @@ func ExamplePrintPodWithShowLabels() {
},
},
}
err := f.PrintObject(cmd, pod, os.Stdout)
mapper, _ := f.Object(false)
err := f.PrintObject(cmd, mapper, pod, os.Stdout)
if err != nil {
fmt.Printf("Unexpected error: %v", err)
}
@@ -660,7 +665,8 @@ func ExamplePrintPodHideTerminated() {
}
cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr)
podList := newAllPhasePodList()
err := f.PrintObject(cmd, podList, os.Stdout)
mapper, _ := f.Object(false)
err := f.PrintObject(cmd, mapper, podList, os.Stdout)
if err != nil {
fmt.Printf("Unexpected error: %v", err)
}
@@ -680,7 +686,8 @@ func ExamplePrintPodShowAll() {
}
cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr)
podList := newAllPhasePodList()
err := f.PrintObject(cmd, podList, os.Stdout)
mapper, _ := f.Object(false)
err := f.PrintObject(cmd, mapper, podList, os.Stdout)
if err != nil {
fmt.Printf("Unexpected error: %v", err)
}
@@ -748,7 +755,9 @@ func ExamplePrintServiceWithNamespacesAndLabels() {
}
ld := util.NewLineDelimiter(os.Stdout, "|")
defer ld.Flush()
err := f.PrintObject(cmd, svc, ld)
mapper, _ := f.Object(false)
err := f.PrintObject(cmd, mapper, svc, ld)
if err != nil {
fmt.Printf("Unexpected error: %v", err)
}

View File

@@ -79,7 +79,7 @@ func NewCmdConvert(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmd.Flags().BoolVar(&options.local, "local", true, "If true, convert will NOT try to contact api-server but run locally.")
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -109,8 +109,9 @@ func (o *ConvertOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.
}
// build the builder
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
clientMapper := resource.ClientMapperFunc(f.ClientForMapping)
if o.local {
fmt.Fprintln(out, "running in local mode...")
o.builder = resource.NewBuilder(mapper, typer, resource.DisabledClientForMapping{ClientMapper: clientMapper}, f.Decoder(true))

View File

@@ -76,6 +76,7 @@ func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
// create subcommands
cmd.AddCommand(NewCmdCreateNamespace(f, out))
@@ -103,7 +104,7 @@ func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *C
return err
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
Schema(schema).
ContinueOnError().
@@ -223,7 +224,7 @@ func RunCreateSubcommand(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer,
if err != nil {
return err
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
gvk, err := typer.ObjectKind(obj)
mapping, err := mapper.RESTMapping(unversioned.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, gvk.Version)
if err != nil {
@@ -257,5 +258,5 @@ func RunCreateSubcommand(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer,
return nil
}
return f.PrintObject(cmd, obj, out)
return f.PrintObject(cmd, mapper, obj, out)
}

View File

@@ -51,6 +51,7 @@ func NewCmdCreateNamespace(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.NamespaceV1GeneratorName)
return cmd
}

View File

@@ -38,6 +38,7 @@ func NewCmdCreateSecret(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
}
cmd.AddCommand(NewCmdCreateSecretDockerRegistry(f, cmdOut))
cmd.AddCommand(NewCmdCreateSecretGeneric(f, cmdOut))
return cmd
}
@@ -155,6 +156,7 @@ func NewCmdCreateSecretDockerRegistry(f *cmdutil.Factory, cmdOut io.Writer) *cob
cmd.Flags().String("docker-email", "", "Email for Docker registry")
cmd.MarkFlagRequired("docker-email")
cmd.Flags().String("docker-server", "https://index.docker.io/v1/", "Server location for Docker registry")
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}

View File

@@ -50,6 +50,7 @@ func NewCmdCreateServiceAccount(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Com
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceAccountV1GeneratorName)
return cmd
}

View File

@@ -100,6 +100,7 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().Int("grace-period", -1, "Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.")
cmd.Flags().Duration("timeout", 0, "The length of time to wait before giving up on a delete, zero means determine a timeout from the size of the object")
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -109,7 +110,7 @@ func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
return err
}
deleteAll := cmdutil.GetFlagBool(cmd, "all")
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().

View File

@@ -89,6 +89,7 @@ func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command {
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -103,7 +104,7 @@ func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s
return cmdutil.UsageError(cmd, "Required resource not specified.")
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().

View File

@@ -60,7 +60,7 @@ kubectl cordon foo
func NewCmdCordon(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &DrainOptions{factory: f, out: out}
return &cobra.Command{
cmd := &cobra.Command{
Use: "cordon NODE",
Short: "Mark node as unschedulable",
Long: cordon_long,
@@ -70,6 +70,7 @@ func NewCmdCordon(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.CheckErr(options.RunCordonOrUncordon(true))
},
}
return cmd
}
const (
@@ -83,7 +84,7 @@ $ kubectl uncordon foo
func NewCmdUncordon(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &DrainOptions{factory: f, out: out}
return &cobra.Command{
cmd := &cobra.Command{
Use: "uncordon NODE",
Short: "Mark node as schedulable",
Long: uncordon_long,
@@ -93,6 +94,7 @@ func NewCmdUncordon(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.CheckErr(options.RunCordonOrUncordon(false))
},
}
return cmd
}
const (
@@ -149,14 +151,14 @@ func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error {
return err
}
o.mapper, o.typer = o.factory.Object()
o.mapper, o.typer = o.factory.Object(false)
cmdNamespace, _, err := o.factory.DefaultNamespace()
if err != nil {
return err
}
r := o.factory.NewBuilder().
r := o.factory.NewBuilder(cmdutil.GetIncludeThirdPartyAPIs(cmd)).
NamespaceParam(cmdNamespace).DefaultNamespace().
ResourceNames("node", args[0]).
Do()

View File

@@ -107,6 +107,7 @@ func NewCmdEdit(f *cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
cmd.Flags().Bool("windows-line-endings", gruntime.GOOS == "windows", "Use Windows line-endings (default Unix line-endings)")
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -129,7 +130,7 @@ func RunEdit(f *cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args
return err
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
resourceMapper := &resource.Mapper{
ObjectTyper: typer,
RESTMapper: mapper,

View File

@@ -52,6 +52,7 @@ func NewCmdExplain(f *cmdutil.Factory, out io.Writer) *cobra.Command {
},
}
cmd.Flags().Bool("recursive", false, "Print the fields of fields (Currently only 1 level deep)")
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -65,7 +66,7 @@ func RunExplain(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st
apiVersionString := cmdutil.GetFlagString(cmd, "api-version")
apiVersion := unversioned.GroupVersion{}
mapper, _ := f.Object()
mapper, _ := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
// TODO: After we figured out the new syntax to separate group and resource, allow
// the users to use it in explain (kubectl explain <group><syntax><resource>).
// Refer to issue #16039 for why we do this. Refer to PR #15808 that used "/" syntax.

View File

@@ -115,7 +115,7 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
return err
}
mapper, typer := f.Object()
mapper, typer := f.Object(false)
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(namespace).DefaultNamespace().
@@ -229,7 +229,7 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
info.Refresh(object, true)
// TODO: extract this flag to a central location, when such a location exists.
if cmdutil.GetFlagBool(cmd, "dry-run") {
return f.PrintObject(cmd, object, out)
return f.PrintObject(cmd, mapper, object, out)
}
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, f.JSONEncoder()); err != nil {
return err
@@ -242,7 +242,7 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
}
if len(cmdutil.GetFlagString(cmd, "output")) > 0 {
return f.PrintObject(cmd, object, out)
return f.PrintObject(cmd, mapper, object, out)
}
cmdutil.PrintSuccess(mapper, false, out, info.Mapping.Resource, info.Name, "exposed")
return nil

View File

@@ -102,6 +102,7 @@ func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -110,7 +111,7 @@ func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *GetOptions) error {
selector := cmdutil.GetFlagString(cmd, "selector")
allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces")
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil {

View File

@@ -100,6 +100,7 @@ func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.")
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -204,8 +205,7 @@ func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
if err != nil {
return cmdutil.UsageError(cmd, err.Error())
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
b := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
@@ -296,7 +296,7 @@ func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
}
outputFormat := cmdutil.GetFlagString(cmd, "output")
if outputFormat != "" {
return f.PrintObject(cmd, outputObj, out)
return f.PrintObject(cmd, mapper, outputObj, out)
}
cmdutil.PrintSuccess(mapper, false, out, info.Mapping.Resource, info.Name, dataChangeMsg)
return nil

View File

@@ -101,6 +101,7 @@ func NewCmdLogs(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().Bool("interactive", false, "If true, prompt the user for input when required.")
cmd.Flags().MarkDeprecated("interactive", "This flag is no longer respected and there is no replacement.")
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -155,7 +156,7 @@ func (o *LogsOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Com
o.ClientMapper = resource.ClientMapperFunc(f.ClientForMapping)
o.Out = out
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
decoder := f.Decoder(true)
if o.Object == nil {
infos, err := resource.NewBuilder(mapper, typer, o.ClientMapper, decoder).

View File

@@ -80,6 +80,7 @@ func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().String("type", "strategic", fmt.Sprintf("The type of patch being provided; one of %v", sets.StringKeySet(patchTypes).List()))
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
usage := "Filename, directory, or URL to a file identifying the resource to update"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
@@ -112,7 +113,7 @@ func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
return fmt.Errorf("unable to parse %q: %v", patch, err)
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().

View File

@@ -87,6 +87,8 @@ func NewCmdReplace(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -114,7 +116,7 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st
return forceReplace(f, out, cmd, args, shortOutput, options)
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
Schema(schema).
ContinueOnError().
@@ -182,7 +184,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
}
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().

View File

@@ -102,6 +102,8 @@ func NewCmdRollingUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().Bool("rollback", false, "If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout")
cmdutil.AddValidateFlags(cmd)
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -190,7 +192,7 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
var keepOldName bool
var replicasDefaulted bool
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
if len(filename) != 0 {
schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir"))
@@ -311,10 +313,10 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
oldRcData.WriteString(oldRc.Name)
newRcData.WriteString(newRc.Name)
} else {
if err := f.PrintObject(cmd, oldRc, oldRcData); err != nil {
if err := f.PrintObject(cmd, mapper, oldRc, oldRcData); err != nil {
return err
}
if err := f.PrintObject(cmd, newRc, newRcData); err != nil {
if err := f.PrintObject(cmd, mapper, newRc, newRcData); err != nil {
return err
}
}
@@ -359,7 +361,7 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
return err
}
if outputFormat != "" {
return f.PrintObject(cmd, newRc, out)
return f.PrintObject(cmd, mapper, newRc, out)
}
kind, err := api.Scheme.ObjectKind(newRc)
if err != nil {

View File

@@ -43,7 +43,6 @@ func NewCmdRollout(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Help()
},
}
// subcommands
cmd.AddCommand(NewCmdRolloutHistory(f, out))
cmd.AddCommand(NewCmdRolloutPause(f, out))

View File

@@ -70,7 +70,7 @@ func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []st
}
revisionDetail := cmdutil.GetFlagInt64(cmd, "revision")
mapper, typer := f.Object()
mapper, typer := f.Object(false)
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil {

View File

@@ -80,7 +80,7 @@ func (o *PauseConfig) CompletePause(f *cmdutil.Factory, cmd *cobra.Command, out
return cmdutil.UsageError(cmd, cmd.Use)
}
o.Mapper, o.Typer = f.Object()
o.Mapper, o.Typer = f.Object(false)
o.PauseObject = f.PauseObject
o.Out = out

View File

@@ -78,7 +78,7 @@ func (o *ResumeConfig) CompleteResume(f *cmdutil.Factory, cmd *cobra.Command, ou
return cmdutil.UsageError(cmd, cmd.Use)
}
o.Mapper, o.Typer = f.Object()
o.Mapper, o.Typer = f.Object(false)
o.ResumeObject = f.ResumeObject
o.Out = out

View File

@@ -79,7 +79,7 @@ func (o *UndoOptions) CompleteUndo(f *cmdutil.Factory, cmd *cobra.Command, out i
}
o.ToRevision = cmdutil.GetFlagInt64(cmd, "to-revision")
o.Mapper, o.Typer = f.Object()
o.Mapper, o.Typer = f.Object(false)
o.Out = out
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()

View File

@@ -87,6 +87,7 @@ func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c
addRunFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -256,7 +257,7 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob
if err != nil {
return err
}
_, typer := f.Object()
_, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(namespace).DefaultNamespace().
@@ -270,7 +271,7 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob
outputFormat := cmdutil.GetFlagString(cmd, "output")
if outputFormat != "" {
return f.PrintObject(cmd, obj, cmdOut)
return f.PrintObject(cmd, mapper, obj, cmdOut)
}
cmdutil.PrintSuccess(mapper, false, cmdOut, mapping.Resource, args[0], "created")
return nil
@@ -421,7 +422,7 @@ func generateService(f *cmdutil.Factory, cmd *cobra.Command, args []string, serv
}
if cmdutil.GetFlagString(cmd, "output") != "" {
return f.PrintObject(cmd, obj, out)
return f.PrintObject(cmd, mapper, obj, out)
}
cmdutil.PrintSuccess(mapper, false, out, mapping.Resource, args[0], "created")
@@ -440,7 +441,7 @@ func createGeneratedObject(f *cmdutil.Factory, cmd *cobra.Command, generator kub
return nil, "", nil, nil, err
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
groupVersionKind, err := typer.ObjectKind(obj)
if err != nil {
return nil, "", nil, nil, err

View File

@@ -302,6 +302,7 @@ func TestGenerateService(t *testing.T) {
cmd.Flags().String("output", "", "")
cmd.Flags().Bool(cmdutil.ApplyAnnotationsFlag, false, "")
cmd.Flags().Bool("record", false, "Record current kubectl command in the resource annotation.")
cmdutil.AddInclude3rdPartyFlags(cmd)
addRunFlags(cmd)
if !test.expectPOST {

View File

@@ -85,6 +85,7 @@ func NewCmdScale(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().Duration("timeout", 0, "The length of time to wait before giving up on a scale operation, zero means don't wait.")
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
usage := "Filename, directory, or URL to a file identifying the resource to set a new size"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
@@ -108,7 +109,7 @@ func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
return err
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().

View File

@@ -77,6 +77,7 @@ func NewCmdStop(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().Int("grace-period", -1, "Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.")
cmd.Flags().Duration("timeout", 0, "The length of time to wait before giving up on a delete, zero means determine a timeout from the size of the object")
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd
}
@@ -86,7 +87,7 @@ func RunStop(f *cmdutil.Factory, cmd *cobra.Command, args []string, out io.Write
return err
}
mapper, typer := f.Object()
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().

View File

@@ -39,6 +39,7 @@ import (
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/apimachinery"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/apis/autoscaling"
"k8s.io/kubernetes/pkg/apis/batch"
@@ -51,6 +52,7 @@ import (
"k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/serializer/json"
utilflag "k8s.io/kubernetes/pkg/util/flag"
@@ -69,8 +71,9 @@ type Factory struct {
clients *ClientCache
flags *pflag.FlagSet
// Returns interfaces for dealing with arbitrary runtime.Objects.
Object func() (meta.RESTMapper, runtime.ObjectTyper)
// Returns interfaces for dealing with arbitrary runtime.Objects. If thirdPartyDiscovery is true, performs API calls
// to discovery dynamic API objects registered by third parties.
Object func(thirdPartyDiscovery bool) (meta.RESTMapper, runtime.ObjectTyper)
// Returns interfaces for decoding objects - if toInternal is set, decoded objects will be converted
// into their internal form (if possible). Eventually the internal form will be removed as an option,
// and only versioned objects will be returned.
@@ -179,6 +182,31 @@ func DefaultGenerators(cmdName string) map[string]kubectl.Generator {
return generators[cmdName]
}
func getGroupVersionKinds(gvks []unversioned.GroupVersionKind, group string) []unversioned.GroupVersionKind {
result := []unversioned.GroupVersionKind{}
for ix := range gvks {
if gvks[ix].Group == group {
result = append(result, gvks[ix])
}
}
return result
}
func makeInterfacesFor(versionList []unversioned.GroupVersion) func(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
accessor := meta.NewAccessor()
return func(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
for ix := range versionList {
if versionList[ix].String() == version.String() {
return &meta.VersionInterfaces{
ObjectConvertor: thirdpartyresourcedata.NewThirdPartyObjectConverter(api.Scheme),
MetadataAccessor: accessor,
}, nil
}
}
return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, versionList)
}
}
// NewFactory creates a factory with the default Kubernetes resources defined
// if optionalClientConfig is nil, then flags will be bound to a new clientcmd.ClientConfig.
// if optionalClientConfig is not nil, then this factory will make use of it.
@@ -199,17 +227,61 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
clients: clients,
flags: flags,
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
// If discoverDynamicAPIs is true, make API calls to the discovery service to find APIs that
// have been dynamically added to the apiserver
Object: func(discoverDynamicAPIs bool) (meta.RESTMapper, runtime.ObjectTyper) {
cfg, err := clientConfig.ClientConfig()
CheckErr(err)
cmdApiVersion := unversioned.GroupVersion{}
if cfg.GroupVersion != nil {
cmdApiVersion = *cfg.GroupVersion
}
if discoverDynamicAPIs {
client, err := clients.ClientForVersion(&unversioned.GroupVersion{Version: "v1"})
CheckErr(err)
versions, gvks, err := GetThirdPartyGroupVersions(client.Discovery())
CheckErr(err)
if len(versions) > 0 {
priorityMapper, ok := mapper.RESTMapper.(meta.PriorityRESTMapper)
if !ok {
CheckErr(fmt.Errorf("expected PriorityMapper, saw: %v", mapper.RESTMapper))
return nil, nil
}
multiMapper, ok := priorityMapper.Delegate.(meta.MultiRESTMapper)
if !ok {
CheckErr(fmt.Errorf("unexpected type: %v", mapper.RESTMapper))
return nil, nil
}
groupsMap := map[string][]unversioned.GroupVersion{}
for _, version := range versions {
groupsMap[version.Group] = append(groupsMap[version.Group], version)
}
for group, versionList := range groupsMap {
preferredExternalVersion := versionList[0]
thirdPartyMapper, err := kubectl.NewThirdPartyResourceMapper(versionList, getGroupVersionKinds(gvks, group))
CheckErr(err)
accessor := meta.NewAccessor()
groupMeta := apimachinery.GroupMeta{
GroupVersion: preferredExternalVersion,
GroupVersions: versionList,
RESTMapper: thirdPartyMapper,
SelfLinker: runtime.SelfLinker(accessor),
InterfacesFor: makeInterfacesFor(versionList),
}
CheckErr(registered.RegisterGroup(groupMeta))
registered.AddThirdPartyAPIGroupVersions(versionList...)
multiMapper = append(meta.MultiRESTMapper{thirdPartyMapper}, multiMapper...)
}
priorityMapper.Delegate = multiMapper
// Re-assign to the RESTMapper here because priorityMapper is actually a copy, so if we
// don't re-assign, the above assignement won't actually update mapper.RESTMapper
mapper.RESTMapper = priorityMapper
}
}
outputRESTMapper := kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersions: []unversioned.GroupVersion{cmdApiVersion}}
// eventually this should allow me choose a group priority based on the order of the discovery doc, for now hardcode a given order
priorityRESTMapper := meta.PriorityRESTMapper{
Delegate: outputRESTMapper,
ResourcePriority: []unversioned.GroupVersionResource{
@@ -223,7 +295,6 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
{Group: metrics.GroupName, Version: meta.AnyVersion, Kind: meta.AnyKind},
},
}
return priorityRESTMapper, api.Scheme
},
Client: func() (*client.Client, error) {
@@ -233,22 +304,39 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
return clients.ClientConfigForVersion(nil)
},
ClientForMapping: func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
gvk := mapping.GroupVersionKind
mappingVersion := mapping.GroupVersionKind.GroupVersion()
client, err := clients.ClientForVersion(&mappingVersion)
c, err := clients.ClientForVersion(&mappingVersion)
if err != nil {
return nil, err
}
switch mapping.GroupVersionKind.Group {
switch gvk.Group {
case api.GroupName:
return client.RESTClient, nil
return c.RESTClient, nil
case autoscaling.GroupName:
return client.AutoscalingClient.RESTClient, nil
return c.AutoscalingClient.RESTClient, nil
case batch.GroupName:
return client.BatchClient.RESTClient, nil
return c.BatchClient.RESTClient, nil
case extensions.GroupName:
return client.ExtensionsClient.RESTClient, nil
return c.ExtensionsClient.RESTClient, nil
case api.SchemeGroupVersion.Group:
return c.RESTClient, nil
case extensions.SchemeGroupVersion.Group:
return c.ExtensionsClient.RESTClient, nil
default:
if !registered.IsThirdPartyAPIGroupVersion(gvk.GroupVersion()) {
return nil, fmt.Errorf("unknown api group/version: %s", gvk.String())
}
cfg, err := clientConfig.ClientConfig()
if err != nil {
return nil, err
}
gv := gvk.GroupVersion()
cfg.GroupVersion = &gv
cfg.APIPath = "/apis"
cfg.Codec = thirdpartyresourcedata.NewCodec(c.ExtensionsClient.RESTClient.Codec(), gvk.Kind)
return restclient.RESTClientFor(cfg)
}
return nil, fmt.Errorf("unable to get RESTClient for resource '%s'", mapping.Resource)
},
Describer: func(mapping *meta.RESTMapping) (kubectl.Describer, error) {
mappingVersion := mapping.GroupVersionKind.GroupVersion()
@@ -810,6 +898,10 @@ func (c *clientSwaggerSchema) ValidateBytes(data []byte) error {
}
return getSchemaAndValidate(c.c.BatchClient.RESTClient, data, "apis/", gvk.GroupVersion().String(), c.cacheDir)
}
if registered.IsThirdPartyAPIGroupVersion(gvk.GroupVersion()) {
// Don't attempt to validate third party objects
return nil
}
if gvk.Group == extensions.GroupName {
if c.c.ExtensionsClient == nil {
return errors.New("unable to validate: no experimental client")
@@ -874,8 +966,7 @@ func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig {
}
// PrintObject prints an api object given command line flags to modify the output format
func (f *Factory) PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error {
mapper, _ := f.Object()
func (f *Factory) PrintObject(cmd *cobra.Command, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error {
gvk, err := api.Scheme.ObjectKind(obj)
if err != nil {
return err
@@ -936,8 +1027,8 @@ func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMappin
}
// One stop shopping for a Builder
func (f *Factory) NewBuilder() *resource.Builder {
mapper, typer := f.Object()
func (f *Factory) NewBuilder(thirdPartyDiscovery bool) *resource.Builder {
mapper, typer := f.Object(thirdPartyDiscovery)
return resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true))
}

View File

@@ -32,6 +32,8 @@ import (
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/client/typed/discovery"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
"k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/resource"
@@ -514,3 +516,53 @@ func ContainsChangeCause(info *resource.Info) bool {
func ShouldRecord(cmd *cobra.Command, info *resource.Info) bool {
return GetRecordFlag(cmd) || ContainsChangeCause(info)
}
func GetThirdPartyGroupVersions(discovery discovery.DiscoveryInterface) ([]unversioned.GroupVersion, []unversioned.GroupVersionKind, error) {
result := []unversioned.GroupVersion{}
gvks := []unversioned.GroupVersionKind{}
groupList, err := discovery.ServerGroups()
if err != nil {
// On forbidden or not found, just return empty lists.
if errors.IsForbidden(err) || errors.IsNotFound(err) {
return result, gvks, nil
}
return nil, nil, err
}
for ix := range groupList.Groups {
group := &groupList.Groups[ix]
for jx := range group.Versions {
gv, err2 := unversioned.ParseGroupVersion(group.Versions[jx].GroupVersion)
if err2 != nil {
return nil, nil, err
}
// Skip GroupVersionKinds that have been statically registered.
if registered.IsRegisteredVersion(gv) {
continue
}
result = append(result, gv)
resourceList, err := discovery.ServerResourcesForGroupVersion(group.Versions[jx].GroupVersion)
if err != nil {
return nil, nil, err
}
for kx := range resourceList.APIResources {
gvks = append(gvks, gv.WithKind(resourceList.APIResources[kx].Kind))
}
}
}
return result, gvks, nil
}
func GetIncludeThirdPartyAPIs(cmd *cobra.Command) bool {
if cmd.Flags().Lookup("include-extended-apis") == nil {
return false
}
return GetFlagBool(cmd, "include-extended-apis")
}
func AddInclude3rdPartyFlags(cmd *cobra.Command) {
cmd.Flags().Bool("include-extended-apis", true, "If true, include definitions of new APIs via calls to the API server. [default true]")
}