Skip to content

new-app: verify if API has required resources enabled #20020

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions pkg/oc/cli/newapp/newapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/discovery"
"k8s.io/client-go/dynamic"
restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api/legacyscheme"
Expand Down Expand Up @@ -176,6 +178,50 @@ func (p *versionedPrintObj) PrintObj(obj runtime.Object, out io.Writer) error {
return printFn(obj)
}

func nonEmpty(str string, def string) string {
if str == "" {
return def
}
return str
}

func checkResources(discoveryClient discovery.DiscoveryInterface, items []runtime.Object) error {
resources, err := discoveryClient.ServerResources()
if err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wozniakjan @soltysh I got here because this particular line didn't tolerate partial discovery. All CLI commands should tolerate partial discovery and only fail if they cannot retrieve sufficient information. There may be cases where all of discovery must match, but this isn't one of them.

return fmt.Errorf("Unable to to get list of available resources: %v", err)
}

resourceMap := make(map[schema.GroupVersionKind]bool)
for _, resourceList := range resources {
for _, resource := range resourceList.APIResources {
listGv, _ := schema.ParseGroupVersion(resourceList.GroupVersion)
gvk := schema.GroupVersionKind{
Group: nonEmpty(resource.Group, listGv.Group),
Version: nonEmpty(resource.Version, listGv.Version),
Kind: resource.Kind,
}
resourceMap[gvk] = true
}
}

declaredResources := make(map[schema.GroupVersionKind]bool)
for _, item := range items {
versioned := kcmdutil.AsDefaultVersionedOrOriginal(item, nil)
declaredResources[versioned.GetObjectKind().GroupVersionKind()] = true
}
missingResources := make([]string, 0)
for r := range declaredResources {
if present := resourceMap[r]; !present {
missingResources = append(missingResources, r.String())
}
}

if len(missingResources) > 0 {
return fmt.Errorf("API server is missing declared resources: %v", strings.Join(missingResources, `, `))
}
return nil
}

//Complete sets all common default options for commands (new-app and new-build)
func (o *ObjectGeneratorOptions) Complete(baseName, commandName string, f kcmdutil.Factory, c *cobra.Command, args []string) error {
cmdutil.WarnAboutCommaSeparation(o.ErrOut, o.Config.Environment, "--env")
Expand Down Expand Up @@ -210,6 +256,11 @@ func (o *ObjectGeneratorOptions) Complete(baseName, commandName string, f kcmdut
return err
}

discoveryClient, err := discovery.NewDiscoveryClientForConfig(clientConfig)
if err != nil {
return fmt.Errorf("Unable to validate if required resources are available: %v", err)
}
o.Config.DiscoveryClient = discoveryClient
o.Action.Bulk.Scheme = legacyscheme.Scheme
o.Action.Bulk.Op = bulk.Creator{Client: dynamicClient, RESTMapper: mapper}.Create
// Retry is used to support previous versions of the API server that will
Expand Down Expand Up @@ -349,6 +400,9 @@ func (o *AppOptions) RunNewApp() error {
if err := HandleError(err, o.BaseName, o.CommandName, o.CommandPath, config, TransformRunError); err != nil {
return err
}
if err := checkResources(config.DiscoveryClient, result.List.Items); err != nil {
return err
}

// set labels explicitly supplied by the user on the command line
if err := SetLabels(config.Labels, result); err != nil {
Expand Down
10 changes: 6 additions & 4 deletions pkg/oc/lib/newapp/cmd/newapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
kutilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/discovery"
kapi "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/core/validation"
kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
Expand Down Expand Up @@ -115,10 +116,11 @@ type AppConfig struct {
Out io.Writer
ErrOut io.Writer

KubeClient kclientset.Interface
ImageClient imageclient.ImageInterface
RouteClient routeclient.RouteInterface
TemplateClient templateclient.TemplateInterface
KubeClient kclientset.Interface
ImageClient imageclient.ImageInterface
RouteClient routeclient.RouteInterface
TemplateClient templateclient.TemplateInterface
DiscoveryClient discovery.DiscoveryInterface

Resolvers

Expand Down